diff options
Diffstat (limited to 'tests/auto/quick')
51 files changed, 1591 insertions, 455 deletions
diff --git a/tests/auto/quick/examples/tst_examples.cpp b/tests/auto/quick/examples/tst_examples.cpp index 233cb33631..872a71011d 100644 --- a/tests/auto/quick/examples/tst_examples.cpp +++ b/tests/auto/quick/examples/tst_examples.cpp @@ -103,6 +103,18 @@ tst_examples::tst_examples() excludedFiles << "views/visualdatamodel/slideshow.qml"; #endif +#ifdef QT_NO_OPENGL + //No support for Particles + excludedFiles << "examples/qml/dynamicscene/dynamicscene.qml"; + excludedFiles << "examples/quick/animation/basics/color-animation.qml"; + excludedFiles << "examples/quick/particles/affectors/content/age.qml"; + excludedFiles << "examples/quick/touchinteraction/multipointtouch/bearwhack.qml"; + excludedFiles << "examples/quick/touchinteraction/multipointtouch/multiflame.qml"; + excludedDirs << "examples/quick/particles"; + // No Support for ShaderEffect + excludedFiles << "src/quick/doc/snippets/qml/animators.qml"; +#endif + } tst_examples::~tst_examples() diff --git a/tests/auto/quick/geometry/tst_geometry.cpp b/tests/auto/quick/geometry/tst_geometry.cpp index 8755e3a1d7..904f85c4c6 100644 --- a/tests/auto/quick/geometry/tst_geometry.cpp +++ b/tests/auto/quick/geometry/tst_geometry.cpp @@ -126,9 +126,9 @@ void GeometryTest::testCustomGeometry() }; static QSGGeometry::Attribute attributes[] = { - { 0, 2, GL_FLOAT, 0, 0}, - { 1, 4, GL_UNSIGNED_BYTE, 0, 0}, - { 2, 4, GL_FLOAT, 0, 0}, + QSGGeometry::Attribute::create(0, 2, QSGGeometry::FloatType, false), + QSGGeometry::Attribute::create(1, 4, QSGGeometry::UnsignedByteType, false), + QSGGeometry::Attribute::create(2, 4, QSGGeometry::FloatType, false) }; static QSGGeometry::AttributeSet set = { 4, 6 * sizeof(float) + 4 * sizeof(unsigned char), attributes }; diff --git a/tests/auto/quick/nodes/tst_nodestest.cpp b/tests/auto/quick/nodes/tst_nodestest.cpp index 16c1174604..63e0aeb324 100644 --- a/tests/auto/quick/nodes/tst_nodestest.cpp +++ b/tests/auto/quick/nodes/tst_nodestest.cpp @@ -31,7 +31,6 @@ #include <QtGui/QOffscreenSurface> #include <QtGui/QOpenGLContext> - #include <QtQuick/qsgnode.h> #include <QtQuick/private/qsgbatchrenderer_p.h> #include <QtQuick/private/qsgnodeupdater_p.h> @@ -76,7 +75,7 @@ private Q_SLOTS: private: QOffscreenSurface *surface; QOpenGLContext *context; - QSGRenderContext *renderContext; + QSGDefaultRenderContext *renderContext; }; void NodesTest::initTestCase() @@ -91,7 +90,8 @@ void NodesTest::initTestCase() QVERIFY(context->create()); QVERIFY(context->makeCurrent(surface)); - renderContext = renderLoop->createRenderContext(renderLoop->sceneGraphContext()); + auto rc = renderLoop->createRenderContext(renderLoop->sceneGraphContext()); + renderContext = static_cast<QSGDefaultRenderContext *>(rc); QVERIFY(renderContext); renderContext->initialize(context); QVERIFY(renderContext->isValid()); @@ -110,7 +110,7 @@ void NodesTest::cleanupTestCase() class DummyRenderer : public QSGBatchRenderer::Renderer { public: - DummyRenderer(QSGRootNode *root, QSGRenderContext *renderContext) + DummyRenderer(QSGRootNode *root, QSGDefaultRenderContext *renderContext) : QSGBatchRenderer::Renderer(renderContext) , changedNode(0) , changedState(0) diff --git a/tests/auto/quick/nokeywords/tst_nokeywords.cpp b/tests/auto/quick/nokeywords/tst_nokeywords.cpp index ffe76cc210..6c94b484ae 100644 --- a/tests/auto/quick/nokeywords/tst_nokeywords.cpp +++ b/tests/auto/quick/nokeywords/tst_nokeywords.cpp @@ -48,13 +48,15 @@ #include <QtQuick/private/qsgadaptationlayer_p.h> #include <QtQuick/private/qsgcontext_p.h> #include <QtQuick/private/qsgcontextplugin_p.h> +#ifndef QT_NO_OPENGL #include <QtQuick/private/qsgdefaultdistancefieldglyphcache_p.h> #include <QtQuick/private/qsgdefaultglyphnode_p.h> -#include <QtQuick/private/qsgdefaultimagenode_p.h> -#include <QtQuick/private/qsgdefaultrectanglenode_p.h> +#include <QtQuick/private/qsgdefaultinternalimagenode_p.h> +#include <QtQuick/private/qsgdefaultinternalrectanglenode_p.h> #include <QtQuick/private/qsgdepthstencilbuffer_p.h> #include <QtQuick/private/qsgdistancefieldglyphnode_p.h> #include <QtQuick/private/qsgdistancefieldutil_p.h> +#endif #include <QtQuick/private/qsggeometry_p.h> #include <QtQuick/private/qsgnode_p.h> #include <QtQuick/private/qsgnodeupdater_p.h> diff --git a/tests/auto/quick/qquickaccessible/qquickaccessible.pro b/tests/auto/quick/qquickaccessible/qquickaccessible.pro index 02915e8e22..537aad882f 100644 --- a/tests/auto/quick/qquickaccessible/qquickaccessible.pro +++ b/tests/auto/quick/qquickaccessible/qquickaccessible.pro @@ -15,10 +15,3 @@ OTHER_FILES += data/checkbuttons.qml \ data/pushbutton.qml \ data/statictext.qml \ data/ignored.qml \ - -wince*: { - accessneeded.files = $$QT.widgets.plugins/accessible/*.dll - accessneeded.path = accessible - DEPLOYMENT += accessneeded -} - diff --git a/tests/auto/quick/qquickanimatedimage/tst_qquickanimatedimage.cpp b/tests/auto/quick/qquickanimatedimage/tst_qquickanimatedimage.cpp index b34f58f7c4..34b9fb6b07 100644 --- a/tests/auto/quick/qquickanimatedimage/tst_qquickanimatedimage.cpp +++ b/tests/auto/quick/qquickanimatedimage/tst_qquickanimatedimage.cpp @@ -179,7 +179,11 @@ void tst_qquickanimatedimage::mirror_running() QImage frame0_expected = frame0.transformed(transform); QImage frame1_expected = frame1.transformed(transform); + if (window.devicePixelRatio() != 1.0 && window.rendererInterface()->graphicsApi() == QSGRendererInterface::Software) + QSKIP("QTBUG-53823"); QCOMPARE(frame0_flipped, frame0_expected); + if (window.devicePixelRatio() != 1.0 && window.rendererInterface()->graphicsApi() == QSGRendererInterface::Software) + QSKIP("QTBUG-53823"); QCOMPARE(frame1_flipped, frame1_expected); delete anim; @@ -212,6 +216,8 @@ void tst_qquickanimatedimage::mirror_notRunning() screenshot = window.grabWindow(); screenshot.save("screen.png"); + if (window.devicePixelRatio() != 1.0 && window.rendererInterface()->graphicsApi() == QSGRendererInterface::Software) + QSKIP("QTBUG-53823"); QCOMPARE(screenshot, expected); // mirroring should not change the current frame or playing status diff --git a/tests/auto/quick/qquickapplication/tst_qquickapplication.cpp b/tests/auto/quick/qquickapplication/tst_qquickapplication.cpp index 1bd163fc4a..114f906736 100644 --- a/tests/auto/quick/qquickapplication/tst_qquickapplication.cpp +++ b/tests/auto/quick/qquickapplication/tst_qquickapplication.cpp @@ -47,6 +47,7 @@ private slots: void active(); void state(); void layoutDirection(); + void font(); void inputMethod(); void styleHints(); void cleanup(); @@ -196,6 +197,21 @@ void tst_qquickapplication::layoutDirection() QCOMPARE(Qt::LayoutDirection(item->property("layoutDirection").toInt()), Qt::LeftToRight); } +void tst_qquickapplication::font() +{ + QQmlComponent component(&engine); + component.setData("import QtQuick 2.0; Item { property font defaultFont: Qt.application.font }", QUrl::fromLocalFile("")); + QQuickItem *item = qobject_cast<QQuickItem *>(component.create()); + QVERIFY(item); + QQuickView view; + item->setParentItem(view.rootObject()); + + QVariant defaultFontProperty = item->property("defaultFont"); + QVERIFY(defaultFontProperty.isValid()); + QCOMPARE(defaultFontProperty.type(), QVariant::Font); + QCOMPARE(defaultFontProperty.value<QFont>(), qApp->font()); +} + void tst_qquickapplication::inputMethod() { // technically not in QQuickApplication, but testing anyway here diff --git a/tests/auto/quick/qquickborderimage/data/mesh.qml b/tests/auto/quick/qquickborderimage/data/mesh.qml new file mode 100644 index 0000000000..203bf25867 --- /dev/null +++ b/tests/auto/quick/qquickborderimage/data/mesh.qml @@ -0,0 +1,22 @@ +import QtQuick 2.8 + +Item { + width: 300 + height: 300 + Image { + id: image + source: "colors.png" + visible: false + } + ShaderEffect { + anchors.fill: parent + property variant source: image + mesh: BorderImageMesh { + border.left: 30 + border.right: 30 + border.top: 30 + border.bottom: 30 + size: image.sourceSize + } + } +} diff --git a/tests/auto/quick/qquickborderimage/data/nonmesh.qml b/tests/auto/quick/qquickborderimage/data/nonmesh.qml new file mode 100644 index 0000000000..7a1830a942 --- /dev/null +++ b/tests/auto/quick/qquickborderimage/data/nonmesh.qml @@ -0,0 +1,11 @@ +import QtQuick 2.8 + +BorderImage { + width: 300 + height: 300 + source: "colors.png" + border.left: 30 + border.right: 30 + border.top: 30 + border.bottom: 30 +} diff --git a/tests/auto/quick/qquickborderimage/qquickborderimage.pro b/tests/auto/quick/qquickborderimage/qquickborderimage.pro index 3e16063559..ba6c01737a 100644 --- a/tests/auto/quick/qquickborderimage/qquickborderimage.pro +++ b/tests/auto/quick/qquickborderimage/qquickborderimage.pro @@ -7,6 +7,7 @@ SOURCES += tst_qquickborderimage.cpp \ ../../shared/testhttpserver.cpp include (../../shared/util.pri) +include (../shared/util.pri) TESTDATA = data/* diff --git a/tests/auto/quick/qquickborderimage/tst_qquickborderimage.cpp b/tests/auto/quick/qquickborderimage/tst_qquickborderimage.cpp index c11ae1e8c9..5d242fab9e 100644 --- a/tests/auto/quick/qquickborderimage/tst_qquickborderimage.cpp +++ b/tests/auto/quick/qquickborderimage/tst_qquickborderimage.cpp @@ -44,6 +44,7 @@ #include "../../shared/testhttpserver.h" #include "../../shared/util.h" +#include "../shared/visualtestutil.h" Q_DECLARE_METATYPE(QQuickImageBase::Status) @@ -75,6 +76,9 @@ private slots: void statusChanges_data(); void sourceSizeChanges(); void progressAndStatusChanges(); +#ifndef QT_NO_OPENGL + void borderImageMesh(); +#endif private: QQmlEngine engine; @@ -242,6 +246,11 @@ void tst_qquickborderimage::mirror() image->setProperty("mirror", true); screenshot = window->grabWindow(); + + window->show(); + QTest::qWaitForWindowExposed(window); + if (window->rendererInterface()->graphicsApi() == QSGRendererInterface::Software) + QSKIP("QTBUG-53823"); QCOMPARE(screenshot, srcPixmap); delete window; @@ -574,7 +583,22 @@ void tst_qquickborderimage::progressAndStatusChanges() delete obj; } +#ifndef QT_NO_OPENGL +void tst_qquickborderimage::borderImageMesh() +{ + QQuickView *window = new QQuickView; + window->setSource(testFileUrl("nonmesh.qml")); + window->show(); + QTest::qWaitForWindowExposed(window); + QImage nonmesh = window->grabWindow(); + + window->setSource(testFileUrl("mesh.qml")); + QImage mesh = window->grabWindow(); + + QVERIFY(QQuickVisualTestUtil::compareImages(mesh, nonmesh)); +} +#endif QTEST_MAIN(tst_qquickborderimage) #include "tst_qquickborderimage.moc" diff --git a/tests/auto/quick/qquickcanvasitem/data/CanvasTestCase.qml b/tests/auto/quick/qquickcanvasitem/data/CanvasTestCase.qml index e49f0ac462..b0fb7fcf8c 100644 --- a/tests/auto/quick/qquickcanvasitem/data/CanvasTestCase.qml +++ b/tests/auto/quick/qquickcanvasitem/data/CanvasTestCase.qml @@ -31,7 +31,9 @@ TestCase { } function createCanvasObject(data) { - return component.createObject(testCase, data.properties); + var canvas = component.createObject(testCase, data.properties); + waitForRendering(canvas); + return canvas; } function comparePixel(ctx,x,y,r,g,b,a, d) diff --git a/tests/auto/quick/qquickcanvasitem/data/tst_canvas.qml b/tests/auto/quick/qquickcanvasitem/data/tst_canvas.qml index 93f85107a7..565f906fb1 100644 --- a/tests/auto/quick/qquickcanvasitem/data/tst_canvas.qml +++ b/tests/auto/quick/qquickcanvasitem/data/tst_canvas.qml @@ -590,6 +590,7 @@ CanvasTestCase { verify(canvas); canvas.width = 100; canvas.height = 100; + waitForRendering(canvas); var ctx = canvas.getContext("2d"); diff --git a/tests/auto/quick/qquickcanvasitem/data/tst_image.qml b/tests/auto/quick/qquickcanvasitem/data/tst_image.qml index 46a038a13c..1f695d7080 100644 --- a/tests/auto/quick/qquickcanvasitem/data/tst_image.qml +++ b/tests/auto/quick/qquickcanvasitem/data/tst_image.qml @@ -667,6 +667,7 @@ CanvasTestCase { var canvas2 = Qt.createQmlObject("import QtQuick 2.0; Canvas{renderTarget:Canvas.Image; renderStrategy:Canvas.Immediate}", canvas); canvas2.width = 100; canvas2.height = 50; + waitForRendering(canvas2); var ctx2 = canvas2.getContext('2d'); ctx2.fillStyle = '#0f0'; ctx2.fillRect(0, 0, 100, 50); diff --git a/tests/auto/quick/qquickflickable/data/contentXY.qml b/tests/auto/quick/qquickflickable/data/contentXY.qml new file mode 100644 index 0000000000..8215976949 --- /dev/null +++ b/tests/auto/quick/qquickflickable/data/contentXY.qml @@ -0,0 +1,6 @@ +import QtQuick 2.0 + +Flickable { + width: 400; height: 400 + contentWidth: 1e11; contentHeight: 1e11 +} diff --git a/tests/auto/quick/qquickflickable/data/keepGrab.qml b/tests/auto/quick/qquickflickable/data/keepGrab.qml new file mode 100644 index 0000000000..32546658d0 --- /dev/null +++ b/tests/auto/quick/qquickflickable/data/keepGrab.qml @@ -0,0 +1,22 @@ +import QtQuick 2.3 + +Flickable { + id: flickable + width: 400 + height: 400 + contentWidth: 800 + contentHeight: 800 + + Rectangle { + x: 200 + y: 200 + width: 400 + height: 400 + color: "green" + MouseArea { + id: ma + objectName: "ma" + anchors.fill: parent + } + } +} diff --git a/tests/auto/quick/qquickflickable/tst_qquickflickable.cpp b/tests/auto/quick/qquickflickable/tst_qquickflickable.cpp index d0f015324c..b774481592 100644 --- a/tests/auto/quick/qquickflickable/tst_qquickflickable.cpp +++ b/tests/auto/quick/qquickflickable/tst_qquickflickable.cpp @@ -93,6 +93,8 @@ private slots: void cleanup(); void contentSize(); void ratios_smallContent(); + void contentXYNotTruncatedToInt(); + void keepGrab(); private: void flickWithTouch(QQuickWindow *window, QTouchDevice *touchDevice, const QPoint &from, const QPoint &to); @@ -1223,7 +1225,9 @@ void tst_qquickflickable::flickOnRelease() QTRY_VERIFY(!flickable->isMoving()); #ifdef Q_OS_MAC +# ifndef QT_NO_OPENGL QEXPECT_FAIL("", "QTBUG-26094 stopping on a full pixel doesn't work on OS X", Continue); +# endif #endif // Stop on a full pixel after user interaction QCOMPARE(flickable->contentY(), (qreal)qRound(flickable->contentY())); @@ -1966,6 +1970,72 @@ void tst_qquickflickable::ratios_smallContent() QCOMPARE(obj->property("widthRatioIs").toDouble(), 1.); } +// QTBUG-48018 +void tst_qquickflickable::contentXYNotTruncatedToInt() +{ + QScopedPointer<QQuickView> window(new QQuickView); + window->setSource(testFileUrl("contentXY.qml")); + QTRY_COMPARE(window->status(), QQuickView::Ready); + QQuickViewTestUtil::centerOnScreen(window.data()); + QQuickViewTestUtil::moveMouseAway(window.data()); + window->show(); + QVERIFY(QTest::qWaitForWindowActive(window.data())); + + QQuickFlickable *flickable = qobject_cast<QQuickFlickable*>(window->rootObject()); + QVERIFY(flickable); + + flickable->setContentX(1e10); + flick(window.data(), QPoint(200, 100), QPoint(100, 100), 50); + + // make sure we are not clipped at 2^31 + QVERIFY(flickable->contentX() > qreal(1e10)); +} + +void tst_qquickflickable::keepGrab() +{ + QScopedPointer<QQuickView> window(new QQuickView); + window->setSource(testFileUrl("keepGrab.qml")); + QTRY_COMPARE(window->status(), QQuickView::Ready); + QQuickViewTestUtil::centerOnScreen(window.data()); + QQuickViewTestUtil::moveMouseAway(window.data()); + window->show(); + QVERIFY(QTest::qWaitForWindowActive(window.data())); + + QQuickFlickable *flickable = qobject_cast<QQuickFlickable*>(window->rootObject()); + QVERIFY(flickable); + + QQuickMouseArea *ma = flickable->findChild<QQuickMouseArea*>("ma"); + QVERIFY(ma); + ma->setPreventStealing(true); + + QPoint pos(250, 250); + moveAndPress(window.data(), pos); + for (int i = 0; i < 6; ++i) { + pos += QPoint(10, 10); + QTest::mouseMove(window.data(), pos); + QTest::qWait(10); + } + QTest::mouseRelease(window.data(), Qt::LeftButton, 0, QPoint(310, 310)); + QTest::qWait(10); + + QCOMPARE(flickable->contentX(), 0.0); + QCOMPARE(flickable->contentY(), 0.0); + + ma->setPreventStealing(false); + + pos = QPoint(250, 250); + moveAndPress(window.data(), pos); + for (int i = 0; i < 6; ++i) { + pos += QPoint(10, 10); + QTest::mouseMove(window.data(), pos); + QTest::qWait(10); + } + QTest::mouseRelease(window.data(), Qt::LeftButton, 0, QPoint(310, 310)); + QTest::qWait(10); + + QVERIFY(flickable->contentX() != 0.0); + QVERIFY(flickable->contentY() != 0.0); +} QTEST_MAIN(tst_qquickflickable) diff --git a/tests/auto/quick/qquickgraphicsinfo/data/basic.qml b/tests/auto/quick/qquickgraphicsinfo/data/basic.qml new file mode 100644 index 0000000000..6ff3b82cec --- /dev/null +++ b/tests/auto/quick/qquickgraphicsinfo/data/basic.qml @@ -0,0 +1,14 @@ +import QtQuick 2.8 + +Item { + property int api: GraphicsInfo.api + + property int shaderType: GraphicsInfo.shaderType + property int shaderCompilationType: GraphicsInfo.shaderCompilationType + property int shaderSourceType: GraphicsInfo.shaderSourceType + + property int majorVersion: GraphicsInfo.majorVersion + property int minorVersion: GraphicsInfo.minorVersion + property int profile: GraphicsInfo.profile + property int renderableType: GraphicsInfo.renderableType +} diff --git a/tests/auto/quick/qquickgraphicsinfo/qquickgraphicsinfo.pro b/tests/auto/quick/qquickgraphicsinfo/qquickgraphicsinfo.pro new file mode 100644 index 0000000000..a4296ad9a2 --- /dev/null +++ b/tests/auto/quick/qquickgraphicsinfo/qquickgraphicsinfo.pro @@ -0,0 +1,14 @@ +CONFIG += testcase +TARGET = tst_qquickgraphicsinfo +SOURCES += tst_qquickgraphicsinfo.cpp + +TESTDATA = data/* +include(../../shared/util.pri) + +osx:CONFIG -= app_bundle + +QT += quick testlib + +OTHER_FILES += \ + data/basic.qml + diff --git a/tests/auto/quick/qquickgraphicsinfo/tst_qquickgraphicsinfo.cpp b/tests/auto/quick/qquickgraphicsinfo/tst_qquickgraphicsinfo.cpp new file mode 100644 index 0000000000..256fa43d2e --- /dev/null +++ b/tests/auto/quick/qquickgraphicsinfo/tst_qquickgraphicsinfo.cpp @@ -0,0 +1,85 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include <QtTest/qtest.h> +#include <QtTest/qsignalspy.h> + +#include <QtQuick/qquickitem.h> +#include <QtQuick/qquickview.h> +#include <QtQuick/qsgrendererinterface.h> + +#include "../../shared/util.h" + +#ifndef QT_NO_OPENGL +#include <QtGui/qopenglcontext.h> +#include <QtGui/qsurfaceformat.h> +#endif + +class tst_QQuickGraphicsInfo : public QQmlDataTest +{ + Q_OBJECT + +private slots: + void testProperties(); +}; + +void tst_QQuickGraphicsInfo::testProperties() +{ + QQuickView view; + view.setSource(QUrl::fromLocalFile("data/basic.qml")); + + view.show(); + QVERIFY(QTest::qWaitForWindowExposed(&view)); + + QSignalSpy spy(&view, SIGNAL(sceneGraphInitialized())); + spy.wait(); + + QObject* obj = view.rootObject(); + QVERIFY(obj); + + QSGRendererInterface *rif = view.rendererInterface(); + const int expectedAPI = rif ? rif->graphicsApi() : QSGRendererInterface::Unknown; + + QCOMPARE(obj->property("api").toInt(), expectedAPI); + +#ifndef QT_NO_OPENGL + if (expectedAPI == QSGRendererInterface::OpenGL) { + QCOMPARE(obj->property("shaderType").toInt(), int(QSGRendererInterface::GLSL)); + QVERIFY(view.openglContext()); + QSurfaceFormat format = view.openglContext()->format(); + QCOMPARE(obj->property("majorVersion").toInt(), format.majorVersion()); + QCOMPARE(obj->property("minorVersion").toInt(), format.minorVersion()); + QCOMPARE(obj->property("profile").toInt(), static_cast<int>(format.profile())); + QCOMPARE(obj->property("renderableType").toInt(), static_cast<int>(format.renderableType())); + } +#endif +} + +QTEST_MAIN(tst_QQuickGraphicsInfo) + +#include "tst_qquickgraphicsinfo.moc" diff --git a/tests/auto/quick/qquickimage/tst_qquickimage.cpp b/tests/auto/quick/qquickimage/tst_qquickimage.cpp index 9274a1ac9e..d345163db5 100644 --- a/tests/auto/quick/qquickimage/tst_qquickimage.cpp +++ b/tests/auto/quick/qquickimage/tst_qquickimage.cpp @@ -306,6 +306,7 @@ void tst_qquickimage::mirror() qreal width = 300; qreal height = 250; + qreal devicePixelRatio = 1.0; foreach (QQuickImage::FillMode fillMode, fillModes) { #if defined(Q_OS_BLACKBERRY) @@ -325,13 +326,15 @@ void tst_qquickimage::mirror() QImage screenshot = window->grabWindow(); screenshots[fillMode] = screenshot; + devicePixelRatio = window->devicePixelRatio(); } foreach (QQuickImage::FillMode fillMode, fillModes) { QPixmap srcPixmap; QVERIFY(srcPixmap.load(testFile("pattern.png"))); - QPixmap expected(width, height); + QPixmap expected(width * (int)devicePixelRatio, height * (int)devicePixelRatio); + expected.setDevicePixelRatio(devicePixelRatio); expected.fill(); QPainter p_e(&expected); QTransform transform; diff --git a/tests/auto/quick/qquickitem2/data/layoutmirroring_window.qml b/tests/auto/quick/qquickitem2/data/layoutmirroring_window.qml new file mode 100644 index 0000000000..3bac0716e8 --- /dev/null +++ b/tests/auto/quick/qquickitem2/data/layoutmirroring_window.qml @@ -0,0 +1,7 @@ +import QtQuick 2.0 +import QtQuick.Window 2.0 + +Window { + LayoutMirroring.enabled: true + LayoutMirroring.childrenInherit: true +} diff --git a/tests/auto/quick/qquickitem2/tst_qquickitem.cpp b/tests/auto/quick/qquickitem2/tst_qquickitem.cpp index 438c7bacf1..6554d749dd 100644 --- a/tests/auto/quick/qquickitem2/tst_qquickitem.cpp +++ b/tests/auto/quick/qquickitem2/tst_qquickitem.cpp @@ -88,6 +88,7 @@ private slots: void keyNavigation_focusReason(); void keyNavigation_loop(); void layoutMirroring(); + void layoutMirroringWindow(); void layoutMirroringIllegalParent(); void smooth(); void antialiasing(); @@ -1776,11 +1777,28 @@ void tst_QQuickItem::layoutMirroring() delete parentItem2; } +void tst_QQuickItem::layoutMirroringWindow() +{ + QQmlComponent component(&engine); + component.loadUrl(testFileUrl("layoutmirroring_window.qml")); + QScopedPointer<QObject> object(component.create()); + QQuickWindow *window = qobject_cast<QQuickWindow *>(object.data()); + QVERIFY(window); + window->show(); + + QQuickItemPrivate *content = QQuickItemPrivate::get(window->contentItem()); + QCOMPARE(content->effectiveLayoutMirror, true); + QCOMPARE(content->inheritedLayoutMirror, true); + QCOMPARE(content->isMirrorImplicit, false); + QCOMPARE(content->inheritMirrorFromParent, true); + QCOMPARE(content->inheritMirrorFromItem, true); +} + void tst_QQuickItem::layoutMirroringIllegalParent() { QQmlComponent component(&engine); component.setData("import QtQuick 2.0; QtObject { LayoutMirroring.enabled: true; LayoutMirroring.childrenInherit: true }", QUrl::fromLocalFile("")); - QTest::ignoreMessage(QtWarningMsg, "<Unknown File>:1:21: QML QtObject: LayoutDirection attached property only works with Items"); + QTest::ignoreMessage(QtWarningMsg, "<Unknown File>:1:21: QML QtObject: LayoutDirection attached property only works with Items and Windows"); QObject *object = component.create(); QVERIFY(object != 0); } @@ -2706,113 +2724,122 @@ void tst_QQuickItem::childrenRectBottomRightCorner() struct TestListener : public QQuickItemChangeListener { - TestListener(bool remove = false) : remove(remove) { reset(); } - - void itemGeometryChanged(QQuickItem *, const QRectF &newGeometry, const QRectF &) override { ++itemGeometryChanges; value = newGeometry; } - void itemSiblingOrderChanged(QQuickItem *) override { ++itemSiblingOrderChanges; } - void itemVisibilityChanged(QQuickItem *) override { ++itemVisibilityChanges; } - void itemOpacityChanged(QQuickItem *) override { ++itemOpacityChanges; } - void itemRotationChanged(QQuickItem *) override { ++itemRotationChanges; } - void itemImplicitWidthChanged(QQuickItem *) override { ++itemImplicitWidthChanges; } - void itemImplicitHeightChanged(QQuickItem *) override { ++itemImplicitHeightChanges; } + TestListener(bool remove = false) : remove(remove) { } + void itemGeometryChanged(QQuickItem *item, QQuickGeometryChange, const QRectF &diff) override + { + record(item, QQuickItemPrivate::Geometry, diff); + } + void itemSiblingOrderChanged(QQuickItem *item) override + { + record(item, QQuickItemPrivate::SiblingOrder); + } + void itemVisibilityChanged(QQuickItem *item) override + { + record(item, QQuickItemPrivate::Visibility); + } + void itemOpacityChanged(QQuickItem *item) override + { + record(item, QQuickItemPrivate::Opacity); + } + void itemRotationChanged(QQuickItem *item) override + { + record(item, QQuickItemPrivate::Rotation); + } + void itemImplicitWidthChanged(QQuickItem *item) override + { + record(item, QQuickItemPrivate::ImplicitWidth); + } + void itemImplicitHeightChanged(QQuickItem *item) override + { + record(item, QQuickItemPrivate::ImplicitHeight); + } void itemDestroyed(QQuickItem *item) override { - ++itemDestructions; - // QTBUG-53453 - if (remove) - QQuickItemPrivate::get(item)->removeItemChangeListener(this, QQuickItemPrivate::Destroyed); + record(item, QQuickItemPrivate::Destroyed); } void itemChildAdded(QQuickItem *item, QQuickItem *child) override { - ++itemChildAdditions; - value = QVariant::fromValue(child); - // QTBUG-53453 - if (remove) - QQuickItemPrivate::get(item)->removeItemChangeListener(this, QQuickItemPrivate::Children); + record(item, QQuickItemPrivate::Children, QVariant::fromValue(child)); } void itemChildRemoved(QQuickItem *item, QQuickItem *child) override { - ++itemChildRemovals; - value = QVariant::fromValue(child); - // QTBUG-53453 - if (remove) - QQuickItemPrivate::get(item)->removeItemChangeListener(this, QQuickItemPrivate::Children); + record(item, QQuickItemPrivate::Children, QVariant::fromValue(child)); } void itemParentChanged(QQuickItem *item, QQuickItem *parent) override { - ++itemParentChanges; - value = QVariant::fromValue(parent); - // QTBUG-53453 - if (remove) - QQuickItemPrivate::get(item)->removeItemChangeListener(this, QQuickItemPrivate::Parent); + record(item, QQuickItemPrivate::Parent, QVariant::fromValue(parent)); } QQuickAnchorsPrivate *anchorPrivate() override { return nullptr; } - void reset() + void record(QQuickItem *item, QQuickItemPrivate::ChangeType change, const QVariant &value = QVariant()) + { + changes += change; + values[change] = value; + // QTBUG-54732 + if (remove) + QQuickItemPrivate::get(item)->removeItemChangeListener(this, change); + } + + int count(QQuickItemPrivate::ChangeType change) const + { + return changes.count(change); + } + + QVariant value(QQuickItemPrivate::ChangeType change) const { - value = QVariant(); - itemGeometryChanges = 0; - itemSiblingOrderChanges = 0; - itemVisibilityChanges = 0; - itemOpacityChanges = 0; - itemDestructions = 0; - itemChildAdditions = 0; - itemChildRemovals = 0; - itemParentChanges = 0; - itemRotationChanges = 0; - itemImplicitWidthChanges = 0; - itemImplicitHeightChanges = 0; + return values.value(change); } bool remove; - QVariant value; - int itemGeometryChanges; - int itemSiblingOrderChanges; - int itemVisibilityChanges; - int itemOpacityChanges; - int itemDestructions; - int itemChildAdditions; - int itemChildRemovals; - int itemParentChanges; - int itemRotationChanges; - int itemImplicitWidthChanges; - int itemImplicitHeightChanges; + QList<QQuickItemPrivate::ChangeType> changes; + QHash<QQuickItemPrivate::ChangeType, QVariant> values; }; void tst_QQuickItem::changeListener() { - QQuickItem item; + QQuickWindow window; + window.show(); + QTest::qWaitForWindowExposed(&window); + + QQuickItem *item = new QQuickItem; TestListener itemListener; - QQuickItemPrivate::get(&item)->addItemChangeListener(&itemListener, QQuickItemPrivate::Geometry | QQuickItemPrivate::ImplicitWidth | QQuickItemPrivate::ImplicitHeight | - QQuickItemPrivate::Opacity | QQuickItemPrivate::Rotation); + QQuickItemPrivate::get(item)->addItemChangeListener(&itemListener, QQuickItemPrivate::ChangeTypes(0xffff)); - item.setImplicitWidth(50); - QCOMPARE(itemListener.itemImplicitWidthChanges, 1); - QCOMPARE(itemListener.itemGeometryChanges, 1); - QCOMPARE(itemListener.value, QVariant(QRectF(0,0,50,0))); + item->setImplicitWidth(10); + QCOMPARE(itemListener.count(QQuickItemPrivate::ImplicitWidth), 1); + QCOMPARE(itemListener.count(QQuickItemPrivate::Geometry), 1); + QCOMPARE(itemListener.value(QQuickItemPrivate::Geometry), QVariant(QRectF(0,0,10,0))); - item.setImplicitHeight(50); - QCOMPARE(itemListener.itemImplicitHeightChanges, 1); - QCOMPARE(itemListener.itemGeometryChanges, 2); - QCOMPARE(itemListener.value, QVariant(QRectF(0,0,50,50))); + item->setImplicitHeight(20); + QCOMPARE(itemListener.count(QQuickItemPrivate::ImplicitHeight), 1); + QCOMPARE(itemListener.count(QQuickItemPrivate::Geometry), 2); + QCOMPARE(itemListener.value(QQuickItemPrivate::Geometry), QVariant(QRectF(0,0,0,20))); - item.setWidth(100); - QCOMPARE(itemListener.itemGeometryChanges, 3); - QCOMPARE(itemListener.value, QVariant(QRectF(0,0,100,50))); + item->setWidth(item->width() + 30); + QCOMPARE(itemListener.count(QQuickItemPrivate::Geometry), 3); + QCOMPARE(itemListener.value(QQuickItemPrivate::Geometry), QVariant(QRectF(0,0,30,0))); - item.setHeight(100); - QCOMPARE(itemListener.itemGeometryChanges, 4); - QCOMPARE(itemListener.value, QVariant(QRectF(0,0,100,100))); + item->setHeight(item->height() + 40); + QCOMPARE(itemListener.count(QQuickItemPrivate::Geometry), 4); + QCOMPARE(itemListener.value(QQuickItemPrivate::Geometry), QVariant(QRectF(0,0,0,40))); - item.setOpacity(0.5); - QCOMPARE(itemListener.itemOpacityChanges, 1); + item->setOpacity(0.5); + QCOMPARE(itemListener.count(QQuickItemPrivate::Opacity), 1); - item.setRotation(90); - QCOMPARE(itemListener.itemRotationChanges, 1); + item->setRotation(90); + QCOMPARE(itemListener.count(QQuickItemPrivate::Rotation), 1); - QQuickItem *parent = new QQuickItem; + item->setParentItem(window.contentItem()); + QCOMPARE(itemListener.count(QQuickItemPrivate::Parent), 1); + + item->setVisible(false); + QCOMPARE(itemListener.count(QQuickItemPrivate::Visibility), 1); + + QQuickItemPrivate::get(item)->removeItemChangeListener(&itemListener, QQuickItemPrivate::ChangeTypes(0xffff)); + + QQuickItem *parent = new QQuickItem(window.contentItem()); TestListener parentListener; QQuickItemPrivate::get(parent)->addItemChangeListener(&parentListener, QQuickItemPrivate::Children); @@ -2824,52 +2851,79 @@ void tst_QQuickItem::changeListener() QQuickItemPrivate::get(child2)->addItemChangeListener(&child2Listener, QQuickItemPrivate::Parent | QQuickItemPrivate::SiblingOrder | QQuickItemPrivate::Destroyed); child1->setParentItem(parent); - QCOMPARE(parentListener.itemChildAdditions, 1); - QCOMPARE(parentListener.value, QVariant::fromValue(child1)); - QCOMPARE(child1Listener.itemParentChanges, 1); - QCOMPARE(child1Listener.value, QVariant::fromValue(parent)); + QCOMPARE(parentListener.count(QQuickItemPrivate::Children), 1); + QCOMPARE(parentListener.value(QQuickItemPrivate::Children), QVariant::fromValue(child1)); + QCOMPARE(child1Listener.count(QQuickItemPrivate::Parent), 1); + QCOMPARE(child1Listener.value(QQuickItemPrivate::Parent), QVariant::fromValue(parent)); child2->setParentItem(parent); - QCOMPARE(parentListener.itemChildAdditions, 2); - QCOMPARE(parentListener.value, QVariant::fromValue(child2)); - QCOMPARE(child2Listener.itemParentChanges, 1); - QCOMPARE(child2Listener.value, QVariant::fromValue(parent)); + QCOMPARE(parentListener.count(QQuickItemPrivate::Children), 2); + QCOMPARE(parentListener.value(QQuickItemPrivate::Children), QVariant::fromValue(child2)); + QCOMPARE(child2Listener.count(QQuickItemPrivate::Parent), 1); + QCOMPARE(child2Listener.value(QQuickItemPrivate::Parent), QVariant::fromValue(parent)); child2->stackBefore(child1); - QCOMPARE(child1Listener.itemSiblingOrderChanges, 1); - QCOMPARE(child2Listener.itemSiblingOrderChanges, 1); + QCOMPARE(child1Listener.count(QQuickItemPrivate::SiblingOrder), 1); + QCOMPARE(child2Listener.count(QQuickItemPrivate::SiblingOrder), 1); child1->setParentItem(nullptr); - QCOMPARE(parentListener.itemChildRemovals, 1); - QCOMPARE(parentListener.value, QVariant::fromValue(child1)); - QCOMPARE(child1Listener.itemParentChanges, 2); - QCOMPARE(child1Listener.value, QVariant::fromValue<QQuickItem *>(nullptr)); + QCOMPARE(parentListener.count(QQuickItemPrivate::Children), 3); + QCOMPARE(parentListener.value(QQuickItemPrivate::Children), QVariant::fromValue(child1)); + QCOMPARE(child1Listener.count(QQuickItemPrivate::Parent), 2); + QCOMPARE(child1Listener.value(QQuickItemPrivate::Parent), QVariant::fromValue<QQuickItem *>(nullptr)); delete child1; - QCOMPARE(child1Listener.itemDestructions, 1); + QCOMPARE(child1Listener.count(QQuickItemPrivate::Destroyed), 1); delete child2; - QCOMPARE(parentListener.itemChildRemovals, 2); - QCOMPARE(parentListener.value, QVariant::fromValue(child2)); - QCOMPARE(child2Listener.itemParentChanges, 2); - QCOMPARE(child2Listener.value, QVariant::fromValue<QQuickItem *>(nullptr)); - QCOMPARE(child2Listener.itemDestructions, 1); + QCOMPARE(parentListener.count(QQuickItemPrivate::Children), 4); + QCOMPARE(parentListener.value(QQuickItemPrivate::Children), QVariant::fromValue(child2)); + QCOMPARE(child2Listener.count(QQuickItemPrivate::Parent), 2); + QCOMPARE(child2Listener.value(QQuickItemPrivate::Parent), QVariant::fromValue<QQuickItem *>(nullptr)); + QCOMPARE(child2Listener.count(QQuickItemPrivate::Destroyed), 1); QQuickItemPrivate::get(parent)->removeItemChangeListener(&parentListener, QQuickItemPrivate::Children); QCOMPARE(QQuickItemPrivate::get(parent)->changeListeners.count(), 0); - // QTBUG-53453: all listeners should get invoked even if they remove themselves while iterating the listeners + // QTBUG-54732: all listeners should get invoked even if they remove themselves while iterating the listeners QList<TestListener *> listeners; for (int i = 0; i < 5; ++i) listeners << new TestListener(true); + // itemVisibilityChanged x 5 + foreach (TestListener *listener, listeners) + QQuickItemPrivate::get(parent)->addItemChangeListener(listener, QQuickItemPrivate::Visibility); + QCOMPARE(QQuickItemPrivate::get(parent)->changeListeners.count(), listeners.count()); + parent->setVisible(false); + foreach (TestListener *listener, listeners) + QCOMPARE(listener->count(QQuickItemPrivate::Visibility), 1); + QCOMPARE(QQuickItemPrivate::get(parent)->changeListeners.count(), 0); + + // itemRotationChanged x 5 + foreach (TestListener *listener, listeners) + QQuickItemPrivate::get(parent)->addItemChangeListener(listener, QQuickItemPrivate::Rotation); + QCOMPARE(QQuickItemPrivate::get(parent)->changeListeners.count(), listeners.count()); + parent->setRotation(90); + foreach (TestListener *listener, listeners) + QCOMPARE(listener->count(QQuickItemPrivate::Rotation), 1); + QCOMPARE(QQuickItemPrivate::get(parent)->changeListeners.count(), 0); + + // itemOpacityChanged x 5 + foreach (TestListener *listener, listeners) + QQuickItemPrivate::get(parent)->addItemChangeListener(listener, QQuickItemPrivate::Opacity); + QCOMPARE(QQuickItemPrivate::get(parent)->changeListeners.count(), listeners.count()); + parent->setOpacity(0.5); + foreach (TestListener *listener, listeners) + QCOMPARE(listener->count(QQuickItemPrivate::Opacity), 1); + QCOMPARE(QQuickItemPrivate::get(parent)->changeListeners.count(), 0); + // itemChildAdded() x 5 foreach (TestListener *listener, listeners) QQuickItemPrivate::get(parent)->addItemChangeListener(listener, QQuickItemPrivate::Children); QCOMPARE(QQuickItemPrivate::get(parent)->changeListeners.count(), listeners.count()); child1 = new QQuickItem(parent); foreach (TestListener *listener, listeners) - QCOMPARE(listener->itemChildAdditions, 1); + QCOMPARE(listener->count(QQuickItemPrivate::Children), 1); QCOMPARE(QQuickItemPrivate::get(parent)->changeListeners.count(), 0); // itemParentChanged() x 5 @@ -2878,9 +2932,36 @@ void tst_QQuickItem::changeListener() QCOMPARE(QQuickItemPrivate::get(child1)->changeListeners.count(), listeners.count()); child1->setParentItem(nullptr); foreach (TestListener *listener, listeners) - QCOMPARE(listener->itemParentChanges, 1); + QCOMPARE(listener->count(QQuickItemPrivate::Parent), 1); QCOMPARE(QQuickItemPrivate::get(child1)->changeListeners.count(), 0); + // itemImplicitWidthChanged() x 5 + foreach (TestListener *listener, listeners) + QQuickItemPrivate::get(parent)->addItemChangeListener(listener, QQuickItemPrivate::ImplicitWidth); + QCOMPARE(QQuickItemPrivate::get(parent)->changeListeners.count(), listeners.count()); + parent->setImplicitWidth(parent->implicitWidth() + 1); + foreach (TestListener *listener, listeners) + QCOMPARE(listener->count(QQuickItemPrivate::ImplicitWidth), 1); + QCOMPARE(QQuickItemPrivate::get(parent)->changeListeners.count(), 0); + + // itemImplicitHeightChanged() x 5 + foreach (TestListener *listener, listeners) + QQuickItemPrivate::get(parent)->addItemChangeListener(listener, QQuickItemPrivate::ImplicitHeight); + QCOMPARE(QQuickItemPrivate::get(parent)->changeListeners.count(), listeners.count()); + parent->setImplicitHeight(parent->implicitHeight() + 1); + foreach (TestListener *listener, listeners) + QCOMPARE(listener->count(QQuickItemPrivate::ImplicitHeight), 1); + QCOMPARE(QQuickItemPrivate::get(parent)->changeListeners.count(), 0); + + // itemGeometryChanged() x 5 + foreach (TestListener *listener, listeners) + QQuickItemPrivate::get(parent)->addItemChangeListener(listener, QQuickItemPrivate::Geometry); + QCOMPARE(QQuickItemPrivate::get(parent)->changeListeners.count(), listeners.count()); + parent->setWidth(parent->width() + 1); + foreach (TestListener *listener, listeners) + QCOMPARE(listener->count(QQuickItemPrivate::Geometry), 1); + QCOMPARE(QQuickItemPrivate::get(parent)->changeListeners.count(), 0); + // itemChildRemoved() x 5 child1->setParentItem(parent); foreach (TestListener *listener, listeners) @@ -2888,7 +2969,7 @@ void tst_QQuickItem::changeListener() QCOMPARE(QQuickItemPrivate::get(parent)->changeListeners.count(), listeners.count()); delete child1; foreach (TestListener *listener, listeners) - QCOMPARE(listener->itemChildRemovals, 1); + QCOMPARE(listener->count(QQuickItemPrivate::Children), 2); QCOMPARE(QQuickItemPrivate::get(parent)->changeListeners.count(), 0); // itemDestroyed() x 5 @@ -2897,7 +2978,7 @@ void tst_QQuickItem::changeListener() QCOMPARE(QQuickItemPrivate::get(parent)->changeListeners.count(), listeners.count()); delete parent; foreach (TestListener *listener, listeners) - QCOMPARE(listener->itemDestructions, 1); + QCOMPARE(listener->count(QQuickItemPrivate::Destroyed), 1); } // QTBUG-13893 @@ -3223,7 +3304,7 @@ void tst_QQuickItem::grab() QVERIFY(root); QQuickItem *item = root->findChild<QQuickItem *>("myItem"); QVERIFY(item); - +#ifndef QT_NO_OPENGL { // Default size (item is 100x100) QSharedPointer<QQuickItemGrabResult> result = item->grabToImage(); QSignalSpy spy(result.data(), SIGNAL(ready())); @@ -3244,7 +3325,7 @@ void tst_QQuickItem::grab() QCOMPARE(image.pixel(0, 0), qRgb(255, 0, 0)); QCOMPARE(image.pixel(49, 49), qRgb(0, 0, 255)); } - +#endif } void tst_QQuickItem::isAncestorOf() diff --git a/tests/auto/quick/qquickitemlayer/tst_qquickitemlayer.cpp b/tests/auto/quick/qquickitemlayer/tst_qquickitemlayer.cpp index 92b7196919..2576a1b0fc 100644 --- a/tests/auto/quick/qquickitemlayer/tst_qquickitemlayer.cpp +++ b/tests/auto/quick/qquickitemlayer/tst_qquickitemlayer.cpp @@ -30,6 +30,7 @@ #include <QtQuick/qquickitem.h> #include <QtQuick/qquickview.h> +#include <QtQuick/qsgrendererinterface.h> #include <QtGui/qopenglcontext.h> #include <QtGui/qopenglfunctions.h> @@ -60,9 +61,10 @@ private slots: void initTestCase() Q_DECL_OVERRIDE; void layerEnabled(); void layerSmooth(); +#ifndef QT_NO_OPENGL void layerMipmap(); void layerEffect(); - +#endif void layerVisibility_data(); void layerVisibility(); @@ -90,17 +92,20 @@ private: bool m_isMesaSoftwareRasterizer; int m_mesaVersion; + bool m_isOpenGLRenderer; }; tst_QQuickItemLayer::tst_QQuickItemLayer() : m_isMesaSoftwareRasterizer(false) , m_mesaVersion(0) + , m_isOpenGLRenderer(true) { } void tst_QQuickItemLayer::initTestCase() { QQmlDataTest::initTestCase(); +#ifndef QT_NO_OPENGL QWindow window; QOpenGLContext context; window.setSurfaceType(QWindow::OpenGLSurface); @@ -129,6 +134,13 @@ void tst_QQuickItemLayer::initTestCase() m_mesaVersion = QT_VERSION_CHECK(major, minor, patch); } } + window.create(); +#endif + QQuickView view; + view.showNormal(); + QTest::qWaitForWindowExposed(&view); + if (view.rendererInterface()->graphicsApi() != QSGRendererInterface::OpenGL) + m_isOpenGLRenderer = false; } // The test draws a red and a blue box next to each other and tests that the @@ -165,8 +177,7 @@ void tst_QQuickItemLayer::layerEnabled() QVERIFY(fb.pixel(0, 0) != fb.pixel(0, fb.height() - 1)); } - - +#ifndef QT_NO_OPENGL // The test draws a one pixel wide line and scales it down by more than a a factor 2 // If mipmpping works, the pixels should be gray, not white or black @@ -192,8 +203,7 @@ void tst_QQuickItemLayer::layerEffect() QCOMPARE(fb.pixel(0, 0), qRgb(0xff, 0, 0)); QCOMPARE(fb.pixel(fb.width() - 1, 0), qRgb(0, 0xff, 0)); } - - +#endif // The test draws a rectangle and verifies that there is padding on each side // as the source rect spans outside the item. The padding is verified using @@ -203,6 +213,9 @@ void tst_QQuickItemLayer::layerSourceRect() if (m_isMesaSoftwareRasterizer && m_mesaVersion < QT_VERSION_CHECK(7, 11, 0)) QSKIP("Mesa Software Rasterizer below version 7.11 does not render this test correctly."); + if (!m_isOpenGLRenderer) + QSKIP("Only OpenGL Renderer supports GLSL ShaderEffects"); + QImage fb = runTest("SourceRect.qml"); // Check that the edges are converted to blue @@ -223,6 +236,10 @@ void tst_QQuickItemLayer::layerIsTextureProvider() { if (m_isMesaSoftwareRasterizer && m_mesaVersion < QT_VERSION_CHECK(7, 11, 0)) QSKIP("Mesa Software Rasterizer below version 7.11 does not render this test correctly."); + + if (!m_isOpenGLRenderer) + QSKIP("Only OpenGL Renderer supports GLSL ShaderEffects"); + QImage fb = runTest("TextureProvider.qml"); QCOMPARE(fb.pixel(0, 0), qRgb(0xff, 0, 0)); QCOMPARE(fb.pixel(fb.width() - 1, 0), qRgb(0, 0xff, 0)); @@ -256,6 +273,9 @@ void tst_QQuickItemLayer::layerVisibility() if (m_isMesaSoftwareRasterizer && m_mesaVersion < QT_VERSION_CHECK(7, 11, 0)) QSKIP("Mesa Software Rasterizer below version 7.11 does not render this test correctly."); + if (!m_isOpenGLRenderer) + QSKIP("Only OpenGL Renderer supports GLSL ShaderEffects"); + QFETCH(bool, visible); QFETCH(bool, effect); QFETCH(qreal, opacity); @@ -304,6 +324,9 @@ void tst_QQuickItemLayer::layerZOrder() if (m_isMesaSoftwareRasterizer && m_mesaVersion < QT_VERSION_CHECK(7, 11, 0)) QSKIP("Mesa Software Rasterizer below version 7.11 does not render this test correctly."); + if (!m_isOpenGLRenderer) + QSKIP("Only OpenGL Renderer supports GLSL ShaderEffects"); + QFETCH(bool, effect); QQuickView view; @@ -338,6 +361,9 @@ void tst_QQuickItemLayer::changeZOrder() if (m_isMesaSoftwareRasterizer && m_mesaVersion < QT_VERSION_CHECK(7, 11, 0)) QSKIP("Mesa Software Rasterizer below version 7.11 does not render this test correctly."); + if (!m_isOpenGLRenderer) + QSKIP("Only OpenGL Renderer supports GLSL ShaderEffects"); + QFETCH(bool, layered); QFETCH(bool, effect); @@ -405,6 +431,10 @@ void tst_QQuickItemLayer::changeSamplerName() { if (m_isMesaSoftwareRasterizer && m_mesaVersion < QT_VERSION_CHECK(7, 11, 0)) QSKIP("Mesa Software Rasterizer below version 7.11 does not render this test correctly."); + + if (!m_isOpenGLRenderer) + QSKIP("Only OpenGL Renderer supports GLSL ShaderEffects"); + QImage fb = runTest("SamplerNameChange.qml"); QCOMPARE(fb.pixel(0, 0), qRgb(0, 0, 0xff)); } @@ -413,6 +443,9 @@ void tst_QQuickItemLayer::itemEffect() { if (m_isMesaSoftwareRasterizer && m_mesaVersion < QT_VERSION_CHECK(7, 11, 0)) QSKIP("Mesa Software Rasterizer below version 7.11 does not render this test correctly."); + if (!m_isOpenGLRenderer) + QSKIP("Only OpenGL Renderer supports GLSL ShaderEffects"); + QImage fb = runTest("ItemEffect.qml"); QCOMPARE(fb.pixel(0, 0), qRgb(0xff, 0, 0)); QCOMPARE(fb.pixel(199, 0), qRgb(0xff, 0, 0)); @@ -448,6 +481,9 @@ void tst_QQuickItemLayer::textureMirroring() { QFETCH(int, mirroring); + if (!m_isOpenGLRenderer) + QSKIP("Only OpenGL Renderer supports GLSL ShaderEffects"); + QQuickView view; view.setSource(testFileUrl("TextureMirroring.qml")); diff --git a/tests/auto/quick/qquicklistview/BLACKLIST b/tests/auto/quick/qquicklistview/BLACKLIST index 269696ce8c..d259c11219 100644 --- a/tests/auto/quick/qquicklistview/BLACKLIST +++ b/tests/auto/quick/qquicklistview/BLACKLIST @@ -2,3 +2,6 @@ * [enforceRange_withoutHighlight] osx +#QTBUG-53863 +[populateTransitions] +opensuse-42.1 diff --git a/tests/auto/quick/qquickloader/data/qmldir b/tests/auto/quick/qquickloader/data/qmldir deleted file mode 100644 index bf42b507c0..0000000000 --- a/tests/auto/quick/qquickloader/data/qmldir +++ /dev/null @@ -1 +0,0 @@ -# For tst_QDeclarativeLoader::networkRequestUrl; no types needed though. diff --git a/tests/auto/quick/qquickloader/tst_qquickloader.cpp b/tests/auto/quick/qquickloader/tst_qquickloader.cpp index fe22a238b2..77af4796b6 100644 --- a/tests/auto/quick/qquickloader/tst_qquickloader.cpp +++ b/tests/auto/quick/qquickloader/tst_qquickloader.cpp @@ -213,7 +213,7 @@ void tst_QQuickLoader::sourceOrComponent_data() QTest::newRow("source with encoded subdir binding") << "source" << "source: encodeURIComponent('subdir/Test.qml')\n" << testFileUrl("subdir/Test.qml") << ""; QTest::newRow("sourceComponent") << "component" << "Component { id: comp; Rectangle { width: 100; height: 50 } }\n sourceComponent: comp\n" << QUrl() << ""; QTest::newRow("invalid source") << "source" << "source: 'IDontExist.qml'\n" << testFileUrl("IDontExist.qml") - << QString(testFileUrl("IDontExist.qml").toString() + ": File not found"); + << QString(testFileUrl("IDontExist.qml").toString() + ": No such file or directory"); } void tst_QQuickLoader::clear() @@ -748,7 +748,7 @@ void tst_QQuickLoader::initialPropertyValuesError_data() << (QStringList() << QString(testFileUrl("initialPropertyValues.error.1.qml").toString() + ":6:5: QML Loader: setSource: value is not an object")); QTest::newRow("nonexistent source url") << testFileUrl("initialPropertyValues.error.2.qml") - << (QStringList() << QString(testFileUrl("NonexistentSourceComponent.qml").toString() + ": File not found")); + << (QStringList() << QString(testFileUrl("NonexistentSourceComponent.qml").toString() + ": No such file or directory")); QTest::newRow("invalid source url") << testFileUrl("initialPropertyValues.error.3.qml") << (QStringList() << QString(testFileUrl("InvalidSourceComponent.qml").toString() + ":5:1: Syntax error")); @@ -901,7 +901,7 @@ void tst_QQuickLoader::asynchronous_data() << QStringList(); QTest::newRow("Non-existent component") << testFileUrl("IDoNotExist.qml") - << (QStringList() << QString(testFileUrl("IDoNotExist.qml").toString() + ": File not found")); + << (QStringList() << QString(testFileUrl("IDoNotExist.qml").toString() + ": No such file or directory")); QTest::newRow("Invalid component") << testFileUrl("InvalidSourceComponent.qml") << (QStringList() << QString(testFileUrl("InvalidSourceComponent.qml").toString() + ":5:1: Syntax error")); diff --git a/tests/auto/quick/qquickmousearea/data/qtbug54019.qml b/tests/auto/quick/qquickmousearea/data/qtbug54019.qml new file mode 100644 index 0000000000..75cca2691a --- /dev/null +++ b/tests/auto/quick/qquickmousearea/data/qtbug54019.qml @@ -0,0 +1,21 @@ +import QtQuick 2.7 + +Item { + width: 200 + height: 200 + MouseArea { + id: ma + property string str: "foo!" + width: 150; height: 150 + hoverEnabled: true + + Rectangle { + anchors.fill: parent + color: ma.containsMouse ? "lightsteelblue" : "gray" + } + Text { + text: ma.str + textFormat: Text.PlainText // consequently Text does not care about hover events + } + } +} diff --git a/tests/auto/quick/qquickmousearea/tst_qquickmousearea.cpp b/tests/auto/quick/qquickmousearea/tst_qquickmousearea.cpp index 5891e67df6..f22528a8a0 100644 --- a/tests/auto/quick/qquickmousearea/tst_qquickmousearea.cpp +++ b/tests/auto/quick/qquickmousearea/tst_qquickmousearea.cpp @@ -29,6 +29,7 @@ #include <QtTest/QtTest> #include <QtTest/QSignalSpy> #include <QtQuick/private/qquickdrag_p.h> +#include <QtQuick/private/qquickitem_p.h> #include <QtQuick/private/qquickmousearea_p.h> #include <QtQuick/private/qquickrectangle_p.h> #include <private/qquickflickable_p.h> @@ -107,6 +108,7 @@ private slots: void hoverPropagation(); void hoverVisible(); void hoverAfterPress(); + void subtreeHoverEnabled(); void disableAfterPress(); void onWheel(); void transformedMouseArea_data(); @@ -124,8 +126,12 @@ private slots: void containsPress_data(); void containsPress(); void ignoreBySource(); + void notPressedAfterStolenGrab(); private: + int startDragDistance() const { + return QGuiApplication::styleHints()->startDragDistance(); + } void acceptedButton_data(); void rejectedButton_data(); QTouchDevice *device; @@ -321,7 +327,8 @@ void tst_QQuickMouseArea::dragging() QVERIFY(!drag->active()); - QTest::mousePress(&window, button, 0, QPoint(100,100)); + QPoint p = QPoint(100,100); + QTest::mousePress(&window, button, 0, p); QVERIFY(!drag->active()); QCOMPARE(blackRect->x(), 50.0); @@ -332,18 +339,32 @@ void tst_QQuickMouseArea::dragging() // The item is moved relative to the position of the mouse when the drag // was triggered, this prevents a sudden change in position when the drag // threshold is exceeded. - QTest::mouseMove(&window, QPoint(111,111), 50); - QTest::mouseMove(&window, QPoint(116,116), 50); - QTest::mouseMove(&window, QPoint(122,122), 50); + int dragThreshold = QGuiApplication::styleHints()->startDragDistance(); + + // move the minimum distance to activate drag + p += QPoint(dragThreshold + 1, dragThreshold + 1); + QTest::mouseMove(&window, p); + QVERIFY(!drag->active()); + + // from here on move the item + p += QPoint(1, 1); + QTest::mouseMove(&window, p); + QTRY_VERIFY(drag->active()); + // on macOS the cursor movement is going through a native event which + // means that it can actually take some time to show + QTRY_COMPARE(blackRect->x(), 50.0 + 1); + QCOMPARE(blackRect->y(), 50.0 + 1); + + p += QPoint(10, 10); + QTest::mouseMove(&window, p); QTRY_VERIFY(drag->active()); QTRY_COMPARE(blackRect->x(), 61.0); QCOMPARE(blackRect->y(), 61.0); - QTest::mouseRelease(&window, button, 0, QPoint(122,122)); - + QTest::mouseRelease(&window, button, 0, p); QTRY_VERIFY(!drag->active()); - QCOMPARE(blackRect->x(), 61.0); + QTRY_COMPARE(blackRect->x(), 61.0); QCOMPARE(blackRect->y(), 61.0); } @@ -532,15 +553,18 @@ void tst_QQuickMouseArea::cancelDragging() QVERIFY(!drag->active()); - QTest::mousePress(&window, Qt::LeftButton, 0, QPoint(100,100)); + QPoint p = QPoint(100,100); + QTest::mousePress(&window, Qt::LeftButton, 0, p); QVERIFY(!drag->active()); QCOMPARE(blackRect->x(), 50.0); QCOMPARE(blackRect->y(), 50.0); - QTest::mouseMove(&window, QPoint(111,111), 50); - QTest::mouseMove(&window, QPoint(116,116), 50); - QTest::mouseMove(&window, QPoint(122,122), 50); + p += QPoint(startDragDistance() + 1, 0); + QTest::mouseMove(&window, p); + + p += QPoint(11, 11); + QTest::mouseMove(&window, p); QTRY_VERIFY(drag->active()); QTRY_COMPARE(blackRect->x(), 61.0); @@ -575,7 +599,8 @@ void tst_QQuickMouseArea::setDragOnPressed() QQuickItem *target = mouseArea->findChild<QQuickItem*>("target"); QVERIFY(target); - QTest::mousePress(&window, Qt::LeftButton, 0, QPoint(100,100)); + QPoint p = QPoint(100, 100); + QTest::mousePress(&window, Qt::LeftButton, 0, p); QQuickDrag *drag = mouseArea->drag(); QVERIFY(drag); @@ -587,19 +612,17 @@ void tst_QQuickMouseArea::setDragOnPressed() // First move event triggers drag, second is acted upon. // This is due to possibility of higher stacked area taking precedence. - QTest::mouseMove(&window, QPoint(111,102)); - QTest::qWait(50); - QTest::mouseMove(&window, QPoint(122,122)); - QTest::qWait(50); + p += QPoint(startDragDistance() + 1, 0); + QTest::mouseMove(&window, p); - QVERIFY(drag->active()); - QCOMPARE(target->x(), 61.0); + p += QPoint(11, 0); + QTest::mouseMove(&window, p); + QTRY_VERIFY(drag->active()); + QTRY_COMPARE(target->x(), 61.0); QCOMPARE(target->y(), 50.0); - QTest::mouseRelease(&window, Qt::LeftButton, 0, QPoint(122,122)); - QTest::qWait(50); - - QVERIFY(!drag->active()); + QTest::mouseRelease(&window, Qt::LeftButton, 0, p); + QTRY_VERIFY(!drag->active()); QCOMPARE(target->x(), 61.0); QCOMPARE(target->y(), 50.0); } @@ -748,7 +771,7 @@ void tst_QQuickMouseArea::onMousePressRejected() QVERIFY(!window.rootObject()->property("mr1_canceled").toBool()); QVERIFY(window.rootObject()->property("mr2_pressed").toBool()); QVERIFY(!window.rootObject()->property("mr2_released").toBool()); - QVERIFY(window.rootObject()->property("mr2_canceled").toBool()); + QVERIFY(!window.rootObject()->property("mr2_canceled").toBool()); QTest::qWait(200); @@ -792,14 +815,14 @@ void tst_QQuickMouseArea::pressedCanceledOnWindowDeactivate() QGuiApplication::sendEvent(&window, &pressEvent); - QVERIFY(window.rootObject()->property("pressed").toBool()); + QTRY_VERIFY(window.rootObject()->property("pressed").toBool()); QVERIFY(!window.rootObject()->property("canceled").toBool()); QCOMPARE(window.rootObject()->property("released").toInt(), expectedRelease); QCOMPARE(window.rootObject()->property("clicked").toInt(), expectedClicks); if (doubleClick) { QGuiApplication::sendEvent(&window, &releaseEvent); - QVERIFY(!window.rootObject()->property("pressed").toBool()); + QTRY_VERIFY(!window.rootObject()->property("pressed").toBool()); QVERIFY(!window.rootObject()->property("canceled").toBool()); QCOMPARE(window.rootObject()->property("released").toInt(), ++expectedRelease); QCOMPARE(window.rootObject()->property("clicked").toInt(), ++expectedClicks); @@ -808,7 +831,7 @@ void tst_QQuickMouseArea::pressedCanceledOnWindowDeactivate() QMouseEvent pressEvent2(QEvent::MouseButtonDblClick, QPoint(100, 100), Qt::LeftButton, Qt::LeftButton, 0); QGuiApplication::sendEvent(&window, &pressEvent2); - QVERIFY(window.rootObject()->property("pressed").toBool()); + QTRY_VERIFY(window.rootObject()->property("pressed").toBool()); QVERIFY(!window.rootObject()->property("canceled").toBool()); QCOMPARE(window.rootObject()->property("released").toInt(), expectedRelease); QCOMPARE(window.rootObject()->property("clicked").toInt(), expectedClicks); @@ -820,23 +843,21 @@ void tst_QQuickMouseArea::pressedCanceledOnWindowDeactivate() secondWindow->setProperty("visible", true); QTest::qWaitForWindowExposed(secondWindow); - QVERIFY(!window.rootObject()->property("pressed").toBool()); + QTRY_VERIFY(!window.rootObject()->property("pressed").toBool()); QVERIFY(window.rootObject()->property("canceled").toBool()); QCOMPARE(window.rootObject()->property("released").toInt(), expectedRelease); QCOMPARE(window.rootObject()->property("clicked").toInt(), expectedClicks); //press again QGuiApplication::sendEvent(&window, &pressEvent); - QVERIFY(window.rootObject()->property("pressed").toBool()); + QTRY_VERIFY(window.rootObject()->property("pressed").toBool()); QVERIFY(!window.rootObject()->property("canceled").toBool()); QCOMPARE(window.rootObject()->property("released").toInt(), expectedRelease); QCOMPARE(window.rootObject()->property("clicked").toInt(), expectedClicks); - QTest::qWait(200); - //release QGuiApplication::sendEvent(&window, &releaseEvent); - QVERIFY(!window.rootObject()->property("pressed").toBool()); + QTRY_VERIFY(!window.rootObject()->property("pressed").toBool()); QVERIFY(!window.rootObject()->property("canceled").toBool()); QCOMPARE(window.rootObject()->property("released").toInt(), ++expectedRelease); QCOMPARE(window.rootObject()->property("clicked").toInt(), ++expectedClicks); @@ -994,48 +1015,60 @@ void tst_QQuickMouseArea::preventStealing() QSignalSpy mousePositionSpy(mouseArea, SIGNAL(positionChanged(QQuickMouseEvent*))); - QTest::mousePress(&window, Qt::LeftButton, 0, QPoint(80, 80)); + QPoint p = QPoint(80, 80); + QTest::mousePress(&window, Qt::LeftButton, 0, p); // Without preventStealing, mouse movement over MouseArea would // cause the Flickable to steal mouse and trigger content movement. - QTest::mouseMove(&window,QPoint(69,69)); - QTest::mouseMove(&window,QPoint(58,58)); - QTest::mouseMove(&window,QPoint(47,47)); + p += QPoint(-startDragDistance() * 2, -startDragDistance() * 2); + QTest::mouseMove(&window, p); + p += QPoint(-10, -10); + QTest::mouseMove(&window, p); + p += QPoint(-10, -10); + QTest::mouseMove(&window, p); + p += QPoint(-10, -10); + QTest::mouseMove(&window, p); - // We should have received all three move events - QCOMPARE(mousePositionSpy.count(), 3); + // We should have received all four move events + QTRY_COMPARE(mousePositionSpy.count(), 4); + mousePositionSpy.clear(); QVERIFY(mouseArea->pressed()); // Flickable content should not have moved. QCOMPARE(flickable->contentX(), 0.); QCOMPARE(flickable->contentY(), 0.); - QTest::mouseRelease(&window, Qt::LeftButton, 0, QPoint(47, 47)); + QTest::mouseRelease(&window, Qt::LeftButton, 0, p); // Now allow stealing and confirm Flickable does its thing. window.rootObject()->setProperty("stealing", false); - QTest::mousePress(&window, Qt::LeftButton, 0, QPoint(80, 80)); + p = QPoint(80, 80); + QTest::mousePress(&window, Qt::LeftButton, 0, p); // Without preventStealing, mouse movement over MouseArea would // cause the Flickable to steal mouse and trigger content movement. - QTest::mouseMove(&window,QPoint(69,69)); - QTest::mouseMove(&window,QPoint(58,58)); - QTest::mouseMove(&window,QPoint(47,47)); + p += QPoint(-startDragDistance() * 2, -startDragDistance() * 2); + QTest::mouseMove(&window, p); + p += QPoint(-10, -10); + QTest::mouseMove(&window, p); + p += QPoint(-10, -10); + QTest::mouseMove(&window, p); + p += QPoint(-10, -10); + QTest::mouseMove(&window, p); // We should only have received the first move event - QCOMPARE(mousePositionSpy.count(), 4); + QTRY_COMPARE(mousePositionSpy.count(), 1); // Our press should be taken away QVERIFY(!mouseArea->pressed()); - // Flickable content should have moved. - - QCOMPARE(flickable->contentX(), 11.); - QCOMPARE(flickable->contentY(), 11.); + // Flickable swallows the first move, then moves 2*10 px + QTRY_COMPARE(flickable->contentX(), 20.); + QCOMPARE(flickable->contentY(), 20.); - QTest::mouseRelease(&window, Qt::LeftButton, 0, QPoint(50, 50)); + QTest::mouseRelease(&window, Qt::LeftButton, 0, p); } void tst_QQuickMouseArea::clickThrough() @@ -1280,6 +1313,26 @@ void tst_QQuickMouseArea::hoverAfterPress() QCOMPARE(mouseArea->hovered(), false); } +void tst_QQuickMouseArea::subtreeHoverEnabled() +{ + QQuickView window; + QByteArray errorMessage; + QVERIFY2(initView(window, testFileUrl("qtbug54019.qml"), true, &errorMessage), errorMessage.constData()); + QQuickItem *root = window.rootObject(); + QVERIFY(root != 0); + + QQuickMouseArea *mouseArea = root->findChild<QQuickMouseArea*>(); + QQuickItemPrivate *rootPrivate = QQuickItemPrivate::get(root); + QVERIFY(mouseArea != 0); + QTest::mouseMove(&window, QPoint(10, 160)); + QCOMPARE(mouseArea->hovered(), false); + QVERIFY(rootPrivate->subtreeHoverEnabled); + QTest::mouseMove(&window, QPoint(10, 10)); + QCOMPARE(mouseArea->hovered(), true); + QTest::mouseMove(&window, QPoint(160, 10)); + QCOMPARE(mouseArea->hovered(), false); +} + void tst_QQuickMouseArea::disableAfterPress() { QQuickView window; @@ -1304,9 +1357,8 @@ void tst_QQuickMouseArea::disableAfterPress() QCOMPARE(blackRect, drag->target()); QVERIFY(!drag->active()); - - QTest::mousePress(&window, Qt::LeftButton, 0, QPoint(100,100)); - + QPoint p = QPoint(100,100); + QTest::mousePress(&window, Qt::LeftButton, 0, p); QTRY_COMPARE(mousePressSpy.count(), 1); QVERIFY(!drag->active()); @@ -1316,22 +1368,24 @@ void tst_QQuickMouseArea::disableAfterPress() // First move event triggers drag, second is acted upon. // This is due to possibility of higher stacked area taking precedence. - QTest::mouseMove(&window, QPoint(111,111)); - QTest::qWait(50); - QTest::mouseMove(&window, QPoint(122,122)); + p += QPoint(startDragDistance() + 1, 0); + QTest::mouseMove(&window, p); + p += QPoint(11, 11); + QTest::mouseMove(&window, p); QTRY_COMPARE(mousePositionSpy.count(), 2); - QVERIFY(drag->active()); - QCOMPARE(blackRect->x(), 61.0); + QTRY_VERIFY(drag->active()); + QTRY_COMPARE(blackRect->x(), 61.0); QCOMPARE(blackRect->y(), 61.0); mouseArea->setEnabled(false); // move should still be acted upon - QTest::mouseMove(&window, QPoint(133,133)); - QTest::qWait(50); - QTest::mouseMove(&window, QPoint(144,144)); + p += QPoint(11, 11); + QTest::mouseMove(&window, p); + p += QPoint(11, 11); + QTest::mouseMove(&window, p); QTRY_COMPARE(mousePositionSpy.count(), 4); @@ -1342,7 +1396,7 @@ void tst_QQuickMouseArea::disableAfterPress() QVERIFY(mouseArea->pressed()); QVERIFY(mouseArea->hovered()); - QTest::mouseRelease(&window, Qt::LeftButton, 0, QPoint(144,144)); + QTest::mouseRelease(&window, Qt::LeftButton, 0, p); QTRY_COMPARE(mouseReleaseSpy.count(), 1); @@ -1599,36 +1653,39 @@ void tst_QQuickMouseArea::changeAxis() QVERIFY(!drag->active()); // Start a diagonal drag - QTest::mousePress(&view, Qt::LeftButton, 0, QPoint(100, 100)); + QPoint p = QPoint(100, 100); + QTest::mousePress(&view, Qt::LeftButton, 0, p); QVERIFY(!drag->active()); QCOMPARE(blackRect->x(), 50.0); QCOMPARE(blackRect->y(), 50.0); - QTest::mouseMove(&view, QPoint(111, 111)); - QTest::qWait(50); - QTest::mouseMove(&view, QPoint(122, 122)); - + p += QPoint(startDragDistance() + 1, startDragDistance() + 1); + QTest::mouseMove(&view, p); + p += QPoint(11, 11); + QTest::mouseMove(&view, p); QTRY_VERIFY(drag->active()); - QCOMPARE(blackRect->x(), 61.0); + QTRY_COMPARE(blackRect->x(), 61.0); QCOMPARE(blackRect->y(), 61.0); QCOMPARE(drag->axis(), QQuickDrag::XAndYAxis); /* When blackRect.x becomes bigger than 75, the drag axis is changed to * Drag.YAxis by the QML code. Verify that this happens, and that the drag * movement is effectively constrained to the Y axis. */ - QTest::mouseMove(&view, QPoint(144, 144)); + p += QPoint(22, 22); + QTest::mouseMove(&view, p); QTRY_COMPARE(blackRect->x(), 83.0); QTRY_COMPARE(blackRect->y(), 83.0); QTRY_COMPARE(drag->axis(), QQuickDrag::YAxis); - QTest::mouseMove(&view, QPoint(155, 155)); + p += QPoint(11, 11); + QTest::mouseMove(&view, p); QTRY_COMPARE(blackRect->y(), 94.0); QCOMPARE(blackRect->x(), 83.0); - QTest::mouseRelease(&view, Qt::LeftButton, 0, QPoint(155, 155)); + QTest::mouseRelease(&view, Qt::LeftButton, 0, p); QTRY_VERIFY(!drag->active()); QCOMPARE(blackRect->x(), 83.0); @@ -1678,11 +1735,17 @@ void tst_QQuickMouseArea::moveAndReleaseWithoutPress() QTest::mousePress(&window, Qt::LeftButton, 0, QPoint(100,100)); + // the press was not accepted, make sure there is no move or release event QTest::mouseMove(&window, QPoint(110,110), 50); - QTRY_COMPARE(root->property("hadMove").toBool(), false); + + // use qwait here because we want to make sure an event does NOT happen + // the test fails if the default state changes, while it shouldn't + QTest::qWait(100); + QCOMPARE(root->property("hadMove").toBool(), false); QTest::mouseRelease(&window, Qt::LeftButton, 0, QPoint(110,110)); - QTRY_COMPARE(root->property("hadRelease").toBool(), false); + QTest::qWait(100); + QCOMPARE(root->property("hadRelease").toBool(), false); } void tst_QQuickMouseArea::nestedStopAtBounds_data() @@ -1926,33 +1989,43 @@ void tst_QQuickMouseArea::ignoreBySource() QVERIFY(flickable); // MouseArea should grab the press because it's interested in non-synthesized mouse events - QTest::mousePress(&window, Qt::LeftButton, 0, QPoint(80, 80)); - QVERIFY(window.mouseGrabberItem() == mouseArea); + QPoint p = QPoint(80, 80); + QTest::mousePress(&window, Qt::LeftButton, 0, p); + QCOMPARE(window.mouseGrabberItem(), mouseArea); // That was a real mouse event - QVERIFY(root->property("lastEventSource").toInt() == Qt::MouseEventNotSynthesized); + QCOMPARE(root->property("lastEventSource").toInt(), int(Qt::MouseEventNotSynthesized)); // Flickable content should not move - QTest::mouseMove(&window,QPoint(69,69)); - QTest::mouseMove(&window,QPoint(58,58)); - QTest::mouseMove(&window,QPoint(47,47)); + p -= QPoint(startDragDistance() + 1, startDragDistance() + 1); + QTest::mouseMove(&window, p); + p -= QPoint(11, 11); + QTest::mouseMove(&window, p); + p -= QPoint(11, 11); + QTest::mouseMove(&window, p); QCOMPARE(flickable->contentX(), 0.); QCOMPARE(flickable->contentY(), 0.); - QTest::mouseRelease(&window, Qt::LeftButton, 0, QPoint(47, 47)); + QTest::mouseRelease(&window, Qt::LeftButton, 0, p); + QCOMPARE(window.mouseGrabberItem(), nullptr); // Now try touch events and confirm that MouseArea ignores them, while Flickable does its thing - - QTest::touchEvent(&window, device).press(0, QPoint(80, 80), &window); + p = QPoint(80, 80); + QTest::touchEvent(&window, device).press(0, p, &window); QQuickTouchUtils::flush(&window); - QVERIFY(window.mouseGrabberItem() != mouseArea); + QCOMPARE(window.mouseGrabberItem(), flickable); + // That was a fake mouse event QCOMPARE(root->property("lastEventSource").toInt(), int(Qt::MouseEventSynthesizedByQt)); - QTest::touchEvent(&window, device).move(0, QPoint(69,69), &window); - QTest::touchEvent(&window, device).move(0, QPoint(69,69), &window); - QTest::touchEvent(&window, device).move(0, QPoint(47,47), &window); + p -= QPoint(startDragDistance() + 1, startDragDistance() + 1); + QTest::touchEvent(&window, device).move(0, p, &window); + p -= QPoint(11, 11); + QTest::touchEvent(&window, device).move(0, p, &window); + p -= QPoint(11, 11); + QTest::touchEvent(&window, device).move(0, p, &window); + QQuickTouchUtils::flush(&window); QCOMPARE(window.mouseGrabberItem(), flickable); - QTest::touchEvent(&window, device).release(0, QPoint(47,47), &window); + QTest::touchEvent(&window, device).release(0, p, &window); QQuickTouchUtils::flush(&window); // Flickable content should have moved @@ -1967,15 +2040,19 @@ void tst_QQuickMouseArea::ignoreBySource() // MouseArea should ignore the press because it's interested in synthesized mouse events - QTest::mousePress(&window, Qt::LeftButton, 0, QPoint(80, 80)); + p = QPoint(80, 80); + QTest::mousePress(&window, Qt::LeftButton, 0, p); QVERIFY(window.mouseGrabberItem() != mouseArea); // That was a real mouse event QVERIFY(root->property("lastEventSource").toInt() == Qt::MouseEventNotSynthesized); // Flickable content should move - QTest::mouseMove(&window,QPoint(69,69)); - QTest::mouseMove(&window,QPoint(58,58)); - QTest::mouseMove(&window,QPoint(47,47)); + p -= QPoint(startDragDistance() + 1, startDragDistance() + 1); + QTest::mouseMove(&window, p); + p -= QPoint(11, 11); + QTest::mouseMove(&window, p); + p -= QPoint(11, 11); + QTest::mouseMove(&window, p); QTRY_VERIFY(flickable->contentX() > 1); QVERIFY(flickable->contentY() > 1); @@ -1984,13 +2061,16 @@ void tst_QQuickMouseArea::ignoreBySource() flickable->setContentY(0); // Now try touch events and confirm that MouseArea gets them, while Flickable doesn't - - QTest::touchEvent(&window, device).press(0, QPoint(80, 80), &window); + p = QPoint(80, 80); + QTest::touchEvent(&window, device).press(0, p, &window); QQuickTouchUtils::flush(&window); QCOMPARE(window.mouseGrabberItem(), mouseArea); - QTest::touchEvent(&window, device).move(0, QPoint(69,69), &window); - QTest::touchEvent(&window, device).move(0, QPoint(69,69), &window); - QTest::touchEvent(&window, device).move(0, QPoint(47,47), &window); + p -= QPoint(startDragDistance() + 1, startDragDistance() + 1); + QTest::touchEvent(&window, device).move(0, p, &window); + p -= QPoint(11, 11); + QTest::touchEvent(&window, device).move(0, p, &window); + p -= QPoint(11, 11); + QTest::touchEvent(&window, device).move(0, p, &window); QQuickTouchUtils::flush(&window); QCOMPARE(window.mouseGrabberItem(), mouseArea); QTest::touchEvent(&window, device).release(0, QPoint(47,47), &window); @@ -2001,6 +2081,23 @@ void tst_QQuickMouseArea::ignoreBySource() QCOMPARE(flickable->contentY(), 0.); } +void tst_QQuickMouseArea::notPressedAfterStolenGrab() +{ + QQuickWindow window; + window.resize(200, 200); + window.show(); + QTest::qWaitForWindowExposed(&window); + + QQuickMouseArea *ma = new QQuickMouseArea(window.contentItem()); + ma->setSize(window.size()); + QObject::connect(ma, + static_cast<void (QQuickMouseArea::*)(QQuickMouseEvent*)>(&QQuickMouseArea::pressed), + [&]() { window.contentItem()->grabMouse(); }); + + QTest::mouseClick(&window, Qt::LeftButton); + QVERIFY(!ma->pressed()); +} + QTEST_MAIN(tst_QQuickMouseArea) #include "tst_qquickmousearea.moc" diff --git a/tests/auto/quick/qquickmultipointtoucharea/tst_qquickmultipointtoucharea.cpp b/tests/auto/quick/qquickmultipointtoucharea/tst_qquickmultipointtoucharea.cpp index c3981c466f..2872556a94 100644 --- a/tests/auto/quick/qquickmultipointtoucharea/tst_qquickmultipointtoucharea.cpp +++ b/tests/auto/quick/qquickmultipointtoucharea/tst_qquickmultipointtoucharea.cpp @@ -915,13 +915,13 @@ void tst_QQuickMultiPointTouchArea::mouseAsTouchpoint() // Touch both, release one, manipulate other touchpoint with mouse QTest::touchEvent(window.data(), device).press(1, touch1); QQuickTouchUtils::flush(window.data()); - QTest::touchEvent(window.data(), device).press(2, touch2); + QTest::touchEvent(window.data(), device).move(1, touch1).press(2, touch2); QQuickTouchUtils::flush(window.data()); QCOMPARE(touch1rect->property("x").toInt(), touch1.x()); QCOMPARE(touch1rect->property("y").toInt(), touch1.y()); QCOMPARE(touch2rect->property("x").toInt(), touch2.x()); QCOMPARE(touch2rect->property("y").toInt(), touch2.y()); - QTest::touchEvent(window.data(), device).release(1, touch1); + QTest::touchEvent(window.data(), device).release(1, touch1).move(2, touch2); touch1.setY(20); QTest::mousePress(window.data(), Qt::LeftButton, 0, touch1); QQuickTouchUtils::flush(window.data()); diff --git a/tests/auto/quick/qquickpainteditem/tst_qquickpainteditem.cpp b/tests/auto/quick/qquickpainteditem/tst_qquickpainteditem.cpp index 1a04526f61..44d7b40ed9 100644 --- a/tests/auto/quick/qquickpainteditem/tst_qquickpainteditem.cpp +++ b/tests/auto/quick/qquickpainteditem/tst_qquickpainteditem.cpp @@ -32,8 +32,11 @@ #include <QtQuick/qquickview.h> #include <private/qquickitem_p.h> +#ifndef QT_NO_OPENGL #include <private/qsgdefaultpainternode_p.h> - +#else +#include <private/qsgsoftwarepainternode_p.h> +#endif class tst_QQuickPaintedItem: public QObject { Q_OBJECT @@ -70,7 +73,7 @@ public: ++paintRequests; clipRect = painter->clipBoundingRect(); } - +#ifndef QT_NO_OPENGL QSGNode *updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData *data) { paintNode = static_cast<QSGDefaultPainterNode *>(QQuickPaintedItem::updatePaintNode(oldNode, data)); @@ -78,6 +81,15 @@ public: } QSGDefaultPainterNode *paintNode; +#else + QSGNode *updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData *data) + { + paintNode = static_cast<QSGSoftwarePainterNode *>(QQuickPaintedItem::updatePaintNode(oldNode, data)); + return paintNode; + } + + QSGSoftwarePainterNode *paintNode; +#endif int paintRequests; QRectF clipRect; }; diff --git a/tests/auto/quick/qquickpincharea/data/pinchproperties.qml b/tests/auto/quick/qquickpincharea/data/pinchproperties.qml index 37d706fc8e..c5daf6cbfe 100644 --- a/tests/auto/quick/qquickpincharea/data/pinchproperties.qml +++ b/tests/auto/quick/qquickpincharea/data/pinchproperties.qml @@ -2,7 +2,7 @@ import QtQuick 2.0 Rectangle { id: whiteRect property variant center - property real scale + property real scale: -1.0 property int pointCount: 0 property bool pinchActive: false width: 240; height: 320 diff --git a/tests/auto/quick/qquickpincharea/tst_qquickpincharea.cpp b/tests/auto/quick/qquickpincharea/tst_qquickpincharea.cpp index aee35b4b90..c1a51fd659 100644 --- a/tests/auto/quick/qquickpincharea/tst_qquickpincharea.cpp +++ b/tests/auto/quick/qquickpincharea/tst_qquickpincharea.cpp @@ -286,6 +286,7 @@ void tst_QQuickPinchArea::pan() QPoint p1(80, 80); QPoint p2(100, 100); { + const int dragThreshold = QGuiApplication::styleHints()->startDragDistance(); QTest::QTouchEventSequence pinchSequence = QTest::touchEvent(window, device); pinchSequence.press(0, p1, window).commit(); QQuickTouchUtils::flush(window); @@ -293,23 +294,63 @@ void tst_QQuickPinchArea::pan() // we have to reuse the same pinchSequence object. pinchSequence.stationary(0).press(1, p2, window).commit(); QQuickTouchUtils::flush(window); - p1 += QPoint(10,10); - p2 += QPoint(10,10); - pinchSequence.move(0, p1,window).move(1, p2,window).commit(); + QVERIFY(!root->property("pinchActive").toBool()); + QCOMPARE(root->property("scale").toReal(), -1.0); + + p1 += QPoint(dragThreshold - 1, 0); + p2 += QPoint(dragThreshold - 1, 0); + pinchSequence.move(0, p1, window).move(1, p2, window).commit(); QQuickTouchUtils::flush(window); + // movement < dragThreshold: pinch not yet active + QVERIFY(!root->property("pinchActive").toBool()); + QCOMPARE(root->property("scale").toReal(), -1.0); - QCOMPARE(root->property("scale").toReal(), 1.0); + // exactly the dragThreshold: pinch starts + p1 += QPoint(1, 0); + p2 += QPoint(1, 0); + pinchSequence.move(0, p1, window).move(1, p2, window).commit(); + QQuickTouchUtils::flush(window); QVERIFY(root->property("pinchActive").toBool()); + QCOMPARE(root->property("scale").toReal(), 1.0); - p1 += QPoint(10,10); - p2 += QPoint(10,10); - pinchSequence.move(0, p1,window).move(1, p2,window).commit(); + // Calculation of the center point is tricky at first: + // center point of the two touch points in item coordinates: + // scene coordinates: (80, 80) + (dragThreshold, 0), (100, 100) + (dragThreshold, 0) + // = ((180+dT)/2, 180/2) = (90+dT, 90) + // item coordinates: (scene) - (50, 50) = (40+dT, 40) + QCOMPARE(root->property("center").toPointF(), QPointF(40 + dragThreshold, 40)); + // pan started, but no actual movement registered yet: + // blackrect starts at 50,50 + QCOMPARE(blackRect->x(), 50.0); + QCOMPARE(blackRect->y(), 50.0); + + p1 += QPoint(10, 0); + p2 += QPoint(10, 0); + pinchSequence.move(0, p1, window).move(1, p2, window).commit(); QQuickTouchUtils::flush(window); - } + QCOMPARE(root->property("center").toPointF(), QPointF(40 + 10 + dragThreshold, 40)); + QCOMPARE(blackRect->x(), 60.0); + QCOMPARE(blackRect->y(), 50.0); - QCOMPARE(root->property("center").toPointF(), QPointF(60, 60)); // blackrect is at 50,50 - QCOMPARE(blackRect->x(), 60.0); - QCOMPARE(blackRect->y(), 60.0); + p1 += QPoint(0, 10); + p2 += QPoint(0, 10); + pinchSequence.move(0, p1, window).move(1, p2, window).commit(); + QQuickTouchUtils::flush(window); + // next big surprise: the center is in item local coordinates and the item was just + // moved 10 to the right... which offsets the center point 10 to the left + QCOMPARE(root->property("center").toPointF(), QPointF(40 + 10 - 10 + dragThreshold, 40 + 10)); + QCOMPARE(blackRect->x(), 60.0); + QCOMPARE(blackRect->y(), 60.0); + + p1 += QPoint(10, 10); + p2 += QPoint(10, 10); + pinchSequence.move(0, p1, window).move(1, p2, window).commit(); + QQuickTouchUtils::flush(window); + // now the item moved again, thus the center point of the touch is moved in total by (10, 10) + QCOMPARE(root->property("center").toPointF(), QPointF(50 + dragThreshold, 50)); + QCOMPARE(blackRect->x(), 70.0); + QCOMPARE(blackRect->y(), 70.0); + } // pan x beyond bound p1 += QPoint(100,100); @@ -318,7 +359,7 @@ void tst_QQuickPinchArea::pan() QQuickTouchUtils::flush(window); QCOMPARE(blackRect->x(), 140.0); - QCOMPARE(blackRect->y(), 160.0); + QCOMPARE(blackRect->y(), 170.0); QTest::touchEvent(window, device).release(0, p1, window).release(1, p2, window); QQuickTouchUtils::flush(window); @@ -470,6 +511,7 @@ void tst_QQuickPinchArea::cancel() QCOMPARE(blackRect->scale(), 1.5); QTouchEvent cancelEvent(QEvent::TouchCancel); + cancelEvent.setDevice(device); QCoreApplication::sendEvent(window, &cancelEvent); QQuickTouchUtils::flush(window); diff --git a/tests/auto/quick/qquickshadereffect/tst_qquickshadereffect.cpp b/tests/auto/quick/qquickshadereffect/tst_qquickshadereffect.cpp index 483cdf7a41..fe33dbd4d8 100644 --- a/tests/auto/quick/qquickshadereffect/tst_qquickshadereffect.cpp +++ b/tests/auto/quick/qquickshadereffect/tst_qquickshadereffect.cpp @@ -30,16 +30,16 @@ #include <QList> #include <QByteArray> -#include <private/qquickshadereffect_p.h> - +#include <private/qquickopenglshadereffect_p.h> +#include <QMatrix4x4> #include <QtQuick/QQuickView> +#include <QtQml/QQmlEngine> #include "../../shared/util.h" - class TestShaderEffect : public QQuickShaderEffect { Q_OBJECT - Q_PROPERTY(QVariant source READ dummyRead NOTIFY dummyChanged) + Q_PROPERTY(QVariant source READ dummyRead NOTIFY sourceChanged) Q_PROPERTY(QVariant _0aA9zZ READ dummyRead NOTIFY dummyChanged) Q_PROPERTY(QVariant x86 READ dummyRead NOTIFY dummyChanged) Q_PROPERTY(QVariant X READ dummyRead NOTIFY dummyChanged) @@ -48,17 +48,18 @@ class TestShaderEffect : public QQuickShaderEffect public: QMatrix4x4 mat4x4Read() const { return QMatrix4x4(1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1); } QVariant dummyRead() const { return QVariant(); } - bool isConnected(const QMetaMethod &signal) const { return m_signals.contains(signal); } + + int signalsConnected = 0; protected: - void connectNotify(const QMetaMethod &signal) { m_signals.append(signal); } - void disconnectNotify(const QMetaMethod &signal) { m_signals.removeOne(signal); } + void connectNotify(const QMetaMethod &) { ++signalsConnected; } + void disconnectNotify(const QMetaMethod &) { --signalsConnected; } signals: void dummyChanged(); + void sourceChanged(); private: - QList<QMetaMethod> m_signals; }; class tst_qquickshadereffect : public QQmlDataTest @@ -84,12 +85,13 @@ private: TexCoordPresent = 0x02, MatrixPresent = 0x04, OpacityPresent = 0x08, - PropertyPresent = 0x10 + SourcePresent = 0x10 }; }; tst_qquickshadereffect::tst_qquickshadereffect() { + qmlRegisterType<TestShaderEffect>("ShaderEffectTest", 1, 0, "TestShaderEffect"); } void tst_qquickshadereffect::initTestCase() @@ -122,7 +124,7 @@ void tst_qquickshadereffect::lookThroughShaderCode_data() "void main() { \n" " gl_FragColor = texture2D(source, qt_TexCoord0) * qt_Opacity; \n" "}") - << (VertexPresent | TexCoordPresent | MatrixPresent | OpacityPresent | PropertyPresent); + << (VertexPresent | TexCoordPresent | MatrixPresent | OpacityPresent | SourcePresent); QTest::newRow("empty") << QByteArray(" ") // one space -- if completely empty, default will be used instead. @@ -135,14 +137,14 @@ void tst_qquickshadereffect::lookThroughShaderCode_data() "attribute highp vec4 qt_Vertex;\n" "// attribute highp vec2 qt_MultiTexCoord0;") << QByteArray("uniform int source; // uniform lowp float qt_Opacity;") - << (VertexPresent | PropertyPresent); + << (VertexPresent | SourcePresent); QTest::newRow("inside block comments") << QByteArray("/*uniform highp mat4 qt_Matrix;\n" "*/attribute highp vec4 qt_Vertex;\n" "/*/attribute highp vec2 qt_MultiTexCoord0;//**/") << QByteArray("/**/uniform int source; /* uniform lowp float qt_Opacity; */") - << (VertexPresent | PropertyPresent); + << (VertexPresent | SourcePresent); QTest::newRow("inside preprocessor directive") << QByteArray("#define uniform\nhighp mat4 qt_Matrix;\n" @@ -150,7 +152,7 @@ void tst_qquickshadereffect::lookThroughShaderCode_data() "#if\\\nattribute highp vec2 qt_MultiTexCoord0;") << QByteArray("uniform int source;\n" " # undef uniform lowp float qt_Opacity;") - << (VertexPresent | PropertyPresent); + << (VertexPresent | SourcePresent); QTest::newRow("line comments between") @@ -158,21 +160,21 @@ void tst_qquickshadereffect::lookThroughShaderCode_data() "attribute//\nhighp//\nvec4//\nqt_Vertex;\n" " //*/ uniform \n attribute //\\ \n highp //// \n vec2 //* \n qt_MultiTexCoord0;") << QByteArray("uniform// lowp float qt_Opacity;\nsampler2D source;") - << (VertexPresent | TexCoordPresent | MatrixPresent | PropertyPresent); + << (VertexPresent | TexCoordPresent | MatrixPresent | SourcePresent); QTest::newRow("block comments between") << QByteArray("uniform/*foo*/highp/*/bar/*/mat4/**//**/qt_Matrix;\n" "attribute/**/highp/**/vec4/**/qt_Vertex;\n" " /* * */ attribute /*///*/ highp /****/ vec2 /**/ qt_MultiTexCoord0;") << QByteArray("uniform/*/ uniform//lowp/*float qt_Opacity;*/sampler2D source;") - << (VertexPresent | TexCoordPresent | MatrixPresent | PropertyPresent); + << (VertexPresent | TexCoordPresent | MatrixPresent | SourcePresent); QTest::newRow("preprocessor directive between") << QByteArray("uniform\n#foo\nhighp\n#bar\nmat4\n#baz\\\nblimey\nqt_Matrix;\n" "attribute\n#\nhighp\n#\nvec4\n#\nqt_Vertex;\n" " #uniform \n attribute \n # foo \n highp \n # bar \n vec2 \n#baz \n qt_MultiTexCoord0;") << QByteArray("uniform\n#if lowp float qt_Opacity;\nsampler2D source;") - << (VertexPresent | TexCoordPresent | MatrixPresent | PropertyPresent); + << (VertexPresent | TexCoordPresent | MatrixPresent | SourcePresent); QTest::newRow("newline between") << QByteArray("uniform\nhighp\nmat4\nqt_Matrix\n;\n" @@ -180,7 +182,7 @@ void tst_qquickshadereffect::lookThroughShaderCode_data() " \n attribute \n highp \n vec2 \n qt_Multi\nTexCoord0 \n ;") << QByteArray("uniform\nsampler2D\nsource;" "uniform lowp float qt_Opacity;") - << (VertexPresent | MatrixPresent | OpacityPresent | PropertyPresent); + << (VertexPresent | MatrixPresent | OpacityPresent | SourcePresent); QTest::newRow("extra characters #1") @@ -221,28 +223,28 @@ void tst_qquickshadereffect::lookThroughShaderCode_data() "attribute highp qt_MultiTexCoord0;\n") << QByteArray("uniform lowp float qt_Opacity;\n" "uniform mediump float source;\n") - << (MatrixPresent | OpacityPresent | PropertyPresent); + << (MatrixPresent | OpacityPresent | SourcePresent); QTest::newRow("property name #1") << QByteArray("uniform highp vec3 _0aA9zZ;") << QByteArray(" ") - << int(PropertyPresent); + << int(SourcePresent); QTest::newRow("property name #2") << QByteArray("uniform mediump vec2 x86;") << QByteArray(" ") - << int(PropertyPresent); + << int(SourcePresent); QTest::newRow("property name #3") << QByteArray("uniform lowp float X;") << QByteArray(" ") - << int(PropertyPresent); + << int(SourcePresent); QTest::newRow("property name #4") << QByteArray("uniform highp mat4 mat4x4;") << QByteArray(" ") - << int(PropertyPresent); + << int(SourcePresent); } void tst_qquickshadereffect::lookThroughShaderCode() @@ -251,9 +253,11 @@ void tst_qquickshadereffect::lookThroughShaderCode() QFETCH(QByteArray, fragmentShader); QFETCH(int, presenceFlags); - TestShaderEffect item; - QMetaMethod dummyChangedSignal = QMetaMethod::fromSignal(&TestShaderEffect::dummyChanged); - QVERIFY(!item.isConnected(dummyChangedSignal)); // Nothing connected yet. + QQmlEngine engine; + QQmlComponent component(&engine); + component.setData("import QtQuick 2.0\nimport ShaderEffectTest 1.0\nTestShaderEffect {}", QUrl()); + QScopedPointer<TestShaderEffect> item(qobject_cast<TestShaderEffect*>(component.create())); + QCOMPARE(item->signalsConnected, 1); QString expected; if ((presenceFlags & VertexPresent) == 0) @@ -265,12 +269,12 @@ void tst_qquickshadereffect::lookThroughShaderCode() if ((presenceFlags & OpacityPresent) == 0) expected += "Warning: Shaders are missing reference to \'qt_Opacity\'.\n"; - item.setVertexShader(vertexShader); - item.setFragmentShader(fragmentShader); - QCOMPARE(item.parseLog(), expected); + item->setVertexShader(vertexShader); + item->setFragmentShader(fragmentShader); + QCOMPARE(item->parseLog(), expected); // If the uniform was successfully parsed, the notify signal has been connected to an update slot. - QCOMPARE(item.isConnected(dummyChangedSignal), (presenceFlags & PropertyPresent) != 0); + QCOMPARE(item->signalsConnected, (presenceFlags & SourcePresent) ? 2 : 1); } void tst_qquickshadereffect::deleteSourceItem() diff --git a/tests/auto/quick/qquicktext/BLACKLIST b/tests/auto/quick/qquicktext/BLACKLIST index c2e7ef03c0..531d981159 100644 --- a/tests/auto/quick/qquicktext/BLACKLIST +++ b/tests/auto/quick/qquicktext/BLACKLIST @@ -2,3 +2,5 @@ * [lineLaidOutRelayout] msvc-2015 +[fontSizeMode] +opensuse-42.1 diff --git a/tests/auto/quick/qquicktext/tst_qquicktext.cpp b/tests/auto/quick/qquicktext/tst_qquicktext.cpp index f31859ee49..2032f72e26 100644 --- a/tests/auto/quick/qquicktext/tst_qquicktext.cpp +++ b/tests/auto/quick/qquicktext/tst_qquicktext.cpp @@ -147,8 +147,9 @@ private slots: void padding(); - void zeroWidthAndElidedDoesntRender(); + void hintingPreference(); + void zeroWidthAndElidedDoesntRender(); void hAlignWidthDependsOnImplicitWidth_data(); void hAlignWidthDependsOnImplicitWidth(); @@ -4165,6 +4166,33 @@ void tst_qquicktext::padding() delete root; } +void tst_qquicktext::hintingPreference() +{ + { + QString componentStr = "import QtQuick 2.0\nText { text: \"Hello world!\" }"; + QQmlComponent textComponent(&engine); + textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile("")); + QQuickText *textObject = qobject_cast<QQuickText*>(textComponent.create()); + + QVERIFY(textObject != 0); + QCOMPARE((int)textObject->font().hintingPreference(), (int)QFont::PreferDefaultHinting); + + delete textObject; + } + { + QString componentStr = "import QtQuick 2.0\nText { text: \"Hello world!\"; font.hintingPreference: Font.PreferNoHinting }"; + QQmlComponent textComponent(&engine); + textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile("")); + QQuickText *textObject = qobject_cast<QQuickText*>(textComponent.create()); + + QVERIFY(textObject != 0); + QCOMPARE((int)textObject->font().hintingPreference(), (int)QFont::PreferNoHinting); + + delete textObject; + } +} + + void tst_qquicktext::zeroWidthAndElidedDoesntRender() { // Tests QTBUG-34990 diff --git a/tests/auto/quick/qquicktextedit/BLACKLIST b/tests/auto/quick/qquicktextedit/BLACKLIST deleted file mode 100644 index 5f3208f848..0000000000 --- a/tests/auto/quick/qquicktextedit/BLACKLIST +++ /dev/null @@ -1,4 +0,0 @@ -[undo] -* -[undo_keypressevents] -* diff --git a/tests/auto/quick/qquicktextedit/tst_qquicktextedit.cpp b/tests/auto/quick/qquicktextedit/tst_qquicktextedit.cpp index cb2a7bfd83..5ed0e9eea7 100644 --- a/tests/auto/quick/qquicktextedit/tst_qquicktextedit.cpp +++ b/tests/auto/quick/qquicktextedit/tst_qquicktextedit.cpp @@ -108,6 +108,7 @@ private slots: void selectionOnFocusOut(); void focusOnPress(); void selection(); + void overwriteMode(); void isRightToLeft_data(); void isRightToLeft(); void keySelection(); @@ -1467,6 +1468,74 @@ void tst_qquicktextedit::selection() QVERIFY(textEditObject->selectedText().isNull()); } +void tst_qquicktextedit::overwriteMode() +{ + QString componentStr = "import QtQuick 2.0\nTextEdit { focus: true; }"; + QQmlComponent textEditComponent(&engine); + textEditComponent.setData(componentStr.toLatin1(), QUrl()); + QQuickTextEdit *textEdit = qobject_cast<QQuickTextEdit*>(textEditComponent.create()); + QVERIFY(textEdit != 0); + + QSignalSpy spy(textEdit, SIGNAL(overwriteModeChanged(bool))); + + QQuickWindow window; + textEdit->setParentItem(window.contentItem()); + window.show(); + window.requestActivate(); + QTest::qWaitForWindowActive(&window); + + QVERIFY(textEdit->hasActiveFocus()); + + textEdit->setOverwriteMode(true); + QCOMPARE(spy.count(), 1); + QCOMPARE(true, textEdit->overwriteMode()); + textEdit->setOverwriteMode(false); + QCOMPARE(spy.count(), 2); + QCOMPARE(false, textEdit->overwriteMode()); + + QVERIFY(!textEdit->overwriteMode()); + QString insertString = "Some first text"; + for (int j = 0; j < insertString.length(); j++) + QTest::keyClick(&window, insertString.at(j).toLatin1()); + + QCOMPARE(textEdit->text(), QString("Some first text")); + + textEdit->setOverwriteMode(true); + QCOMPARE(spy.count(), 3); + textEdit->setCursorPosition(5); + + insertString = "shiny"; + for (int j = 0; j < insertString.length(); j++) + QTest::keyClick(&window, insertString.at(j).toLatin1()); + QCOMPARE(textEdit->text(), QString("Some shiny text")); + + textEdit->setCursorPosition(textEdit->text().length()); + QTest::keyClick(&window, Qt::Key_Enter); + + textEdit->setOverwriteMode(false); + QCOMPARE(spy.count(), 4); + + insertString = "Second paragraph"; + + for (int j = 0; j < insertString.length(); j++) + QTest::keyClick(&window, insertString.at(j).toLatin1()); + QCOMPARE(textEdit->lineCount(), 2); + + textEdit->setCursorPosition(15); + + QCOMPARE(textEdit->cursorPosition(), 15); + + textEdit->setOverwriteMode(true); + QCOMPARE(spy.count(), 5); + + insertString = " blah"; + for (int j = 0; j < insertString.length(); j++) + QTest::keyClick(&window, insertString.at(j).toLatin1()); + QCOMPARE(textEdit->lineCount(), 2); + + QCOMPARE(textEdit->text(), QString("Some shiny text blah\nSecond paragraph")); +} + void tst_qquicktextedit::isRightToLeft_data() { QTest::addColumn<QString>("text"); diff --git a/tests/auto/quick/qquicktextinput/tst_qquicktextinput.cpp b/tests/auto/quick/qquicktextinput/tst_qquicktextinput.cpp index ea88f9dadb..8dc3053d89 100644 --- a/tests/auto/quick/qquicktextinput/tst_qquicktextinput.cpp +++ b/tests/auto/quick/qquicktextinput/tst_qquicktextinput.cpp @@ -105,6 +105,7 @@ private slots: void wrap(); void selection(); void persistentSelection(); + void overwriteMode(); void isRightToLeft_data(); void isRightToLeft(); void moveCursorSelection_data(); @@ -782,6 +783,48 @@ void tst_qquicktextinput::persistentSelection() QCOMPARE(input->property("selected").toString(), QLatin1String("ell")); } +void tst_qquicktextinput::overwriteMode() +{ + QString componentStr = "import QtQuick 2.0\nTextInput { focus: true; }"; + QQmlComponent textInputComponent(&engine); + textInputComponent.setData(componentStr.toLatin1(), QUrl()); + QQuickTextInput *textInput = qobject_cast<QQuickTextInput*>(textInputComponent.create()); + QVERIFY(textInput != 0); + + QSignalSpy spy(textInput, SIGNAL(overwriteModeChanged(bool))); + + QQuickWindow window; + textInput->setParentItem(window.contentItem()); + window.show(); + window.requestActivate(); + QTest::qWaitForWindowActive(&window); + + QVERIFY(textInput->hasActiveFocus()); + + textInput->setOverwriteMode(true); + QCOMPARE(spy.count(), 1); + QCOMPARE(true, textInput->overwriteMode()); + textInput->setOverwriteMode(false); + QCOMPARE(spy.count(), 2); + QCOMPARE(false, textInput->overwriteMode()); + + QVERIFY(!textInput->overwriteMode()); + QString insertString = "Some first text"; + for (int j = 0; j < insertString.length(); j++) + QTest::keyClick(&window, insertString.at(j).toLatin1()); + + QCOMPARE(textInput->text(), QString("Some first text")); + + textInput->setOverwriteMode(true); + QCOMPARE(spy.count(), 3); + textInput->setCursorPosition(5); + + insertString = "shiny"; + for (int j = 0; j < insertString.length(); j++) + QTest::keyClick(&window, insertString.at(j).toLatin1()); + QCOMPARE(textInput->text(), QString("Some shiny text")); +} + void tst_qquicktextinput::isRightToLeft_data() { QTest::addColumn<QString>("text"); diff --git a/tests/auto/quick/qquickview/tst_qquickview.cpp b/tests/auto/quick/qquickview/tst_qquickview.cpp index 05922ae20f..fa9192edb4 100644 --- a/tests/auto/quick/qquickview/tst_qquickview.cpp +++ b/tests/auto/quick/qquickview/tst_qquickview.cpp @@ -36,6 +36,30 @@ #include <QtCore/QDebug> #include <QtQml/qqmlengine.h> +class SizeChangesListener : public QObject, public QVector<QSize> +{ + Q_OBJECT +public: + explicit SizeChangesListener(QQuickItem *item); +private slots: + void onSizeChanged(); +private: + QQuickItem *item; + +}; + +SizeChangesListener::SizeChangesListener(QQuickItem *item) : + item(item) +{ + connect(item, &QQuickItem::widthChanged, this, &SizeChangesListener::onSizeChanged); + connect(item, &QQuickItem::heightChanged, this, &SizeChangesListener::onSizeChanged); +} + +void SizeChangesListener::onSizeChanged() +{ + append(QSize(item->width(), item->height())); +} + class tst_QQuickView : public QQmlDataTest { Q_OBJECT @@ -127,7 +151,6 @@ void tst_QQuickView::resizemodeitem() QCOMPARE(item->width(), 80.0); QCOMPARE(item->height(), 100.0); QTRY_COMPARE(view->size(), QSize(80, 100)); - QCOMPARE(view->size(), QSize(80, 100)); QCOMPARE(view->size(), view->sizeHint()); // size update from root object disabled @@ -139,8 +162,16 @@ void tst_QQuickView::resizemodeitem() QCOMPARE(QSize(item->width(), item->height()), view->sizeHint()); // size update from view + QCoreApplication::processEvents(); // make sure the last resize events are gone + SizeChangesListener sizeListener(item); view->resize(QSize(200,300)); QTRY_COMPARE(item->width(), 200.0); + + for (int i = 0; i < sizeListener.count(); ++i) { + // Check that we have the correct geometry on all signals + QCOMPARE(sizeListener.at(i), view->size()); + } + QCOMPARE(item->height(), 300.0); QCOMPARE(view->size(), QSize(200, 300)); QCOMPARE(view->size(), view->sizeHint()); diff --git a/tests/auto/quick/qquickwindow/qquickwindow.pro b/tests/auto/quick/qquickwindow/qquickwindow.pro index f0d287f30f..05093ba8e0 100644 --- a/tests/auto/quick/qquickwindow/qquickwindow.pro +++ b/tests/auto/quick/qquickwindow/qquickwindow.pro @@ -7,7 +7,7 @@ include(../shared/util.pri) macx:CONFIG -= app_bundle -QT += core-private gui-private qml-private quick-private testlib +QT += core-private qml-private quick-private testlib TESTDATA = data/* diff --git a/tests/auto/quick/qquickwindow/tst_qquickwindow.cpp b/tests/auto/quick/qquickwindow/tst_qquickwindow.cpp index 1365e8b751..acccac8eca 100644 --- a/tests/auto/quick/qquickwindow/tst_qquickwindow.cpp +++ b/tests/auto/quick/qquickwindow/tst_qquickwindow.cpp @@ -40,10 +40,11 @@ #include "../shared/visualtestutil.h" #include "../shared/viewtestutil.h" #include <QSignalSpy> -#include <qpa/qwindowsysteminterface.h> #include <private/qquickwindow_p.h> #include <private/qguiapplication_p.h> #include <QRunnable> +#include <QOpenGLFunctions> +#include <QSGRendererInterface> struct TouchEventData { QEvent::Type type; @@ -156,6 +157,7 @@ public: lastVelocity = lastVelocityFromMouseMove = QVector2D(); lastMousePos = QPointF(); lastMouseCapabilityFlags = 0; + touchEventCount = 0; } static void clearMousePressCounter() @@ -273,25 +275,18 @@ class tst_qquickwindow : public QQmlDataTest Q_OBJECT public: tst_qquickwindow() + : touchDevice(QTest::createTouchDevice()) + , touchDeviceWithVelocity(QTest::createTouchDevice()) { QQuickWindow::setDefaultAlphaBuffer(true); + touchDeviceWithVelocity->setCapabilities(QTouchDevice::Position | QTouchDevice::Velocity); } private slots: - void initTestCase() - { - QQmlDataTest::initTestCase(); - touchDevice = new QTouchDevice; - touchDevice->setType(QTouchDevice::TouchScreen); - QWindowSystemInterface::registerTouchDevice(touchDevice); - touchDeviceWithVelocity = new QTouchDevice; - touchDeviceWithVelocity->setType(QTouchDevice::TouchScreen); - touchDeviceWithVelocity->setCapabilities(QTouchDevice::Position | QTouchDevice::Velocity); - QWindowSystemInterface::registerTouchDevice(touchDeviceWithVelocity); - } void cleanup(); - +#ifndef QT_NO_OPENGL void openglContextCreatedSignal(); +#endif void aboutToStopSignal(); void constantUpdates(); @@ -308,6 +303,9 @@ private slots: void touchEvent_reentrant(); void touchEvent_velocity(); + void mergeTouchPointLists_data(); + void mergeTouchPointLists(); + void mouseFromTouch_basic(); void clearWindow(); @@ -368,18 +366,21 @@ private slots: void testHoverChildMouseEventFilter(); void testHoverTimestamp(); + + void pointerEventTypeAndPointCount(); + private: QTouchDevice *touchDevice; QTouchDevice *touchDeviceWithVelocity; }; - +#ifndef QT_NO_OPENGL Q_DECLARE_METATYPE(QOpenGLContext *); - +#endif void tst_qquickwindow::cleanup() { QVERIFY(QGuiApplication::topLevelWindows().isEmpty()); } - +#ifndef QT_NO_OPENGL void tst_qquickwindow::openglContextCreatedSignal() { qRegisterMetaType<QOpenGLContext *>(); @@ -391,12 +392,15 @@ void tst_qquickwindow::openglContextCreatedSignal() window.show(); QTest::qWaitForWindowExposed(&window); + if (window.rendererInterface()->graphicsApi() != QSGRendererInterface::OpenGL) + QSKIP("Skipping OpenGL context test due to not running with OpenGL"); + QVERIFY(spy.size() > 0); QVariant ctx = spy.at(0).at(0); QCOMPARE(qvariant_cast<QOpenGLContext *>(ctx), window.openglContext()); } - +#endif void tst_qquickwindow::aboutToStopSignal() { QQuickWindow window; @@ -438,8 +442,7 @@ void tst_qquickwindow::constantUpdatesOnWindow_data() window.setGeometry(100, 100, 300, 200); window.show(); QTest::qWaitForWindowExposed(&window); - bool threaded = window.openglContext()->thread() != QGuiApplication::instance()->thread(); - + const bool threaded = QQuickWindowPrivate::get(&window)->context->thread() != QGuiApplication::instance()->thread(); if (threaded) { QTest::newRow("blocked, beforeRender") << true << QByteArray(SIGNAL(beforeRendering())); QTest::newRow("blocked, afterRender") << true << QByteArray(SIGNAL(afterRendering())); @@ -525,9 +528,8 @@ void tst_qquickwindow::touchEvent_basic() // press single point QTest::touchEvent(window, touchDevice).press(0, topItem->mapToScene(pos).toPoint(),window); - QTest::qWait(50); - - QCOMPARE(topItem->lastEvent.touchPoints.count(), 1); + QQuickTouchUtils::flush(window); + QTRY_COMPARE(topItem->lastEvent.touchPoints.count(), 1); QVERIFY(middleItem->lastEvent.touchPoints.isEmpty()); QVERIFY(bottomItem->lastEvent.touchPoints.isEmpty()); @@ -535,9 +537,10 @@ void tst_qquickwindow::touchEvent_basic() // would put the decorated window at that position rather than the window itself. COMPARE_TOUCH_DATA(topItem->lastEvent, makeTouchData(QEvent::TouchBegin, window, Qt::TouchPointPressed, makeTouchPoint(topItem, pos))); topItem->reset(); + QTest::touchEvent(window, touchDevice).release(0, topItem->mapToScene(pos).toPoint(), window); // press multiple points - QTest::touchEvent(window, touchDevice).press(0, topItem->mapToScene(pos).toPoint(),window) + QTest::touchEvent(window, touchDevice).press(0, topItem->mapToScene(pos).toPoint(), window) .press(1, bottomItem->mapToScene(pos).toPoint(), window); QQuickTouchUtils::flush(window); QCOMPARE(topItem->lastEvent.touchPoints.count(), 1); @@ -547,6 +550,7 @@ void tst_qquickwindow::touchEvent_basic() COMPARE_TOUCH_DATA(bottomItem->lastEvent, makeTouchData(QEvent::TouchBegin, window, Qt::TouchPointPressed, makeTouchPoint(bottomItem, pos))); topItem->reset(); bottomItem->reset(); + QTest::touchEvent(window, touchDevice).release(0, topItem->mapToScene(pos).toPoint(), window).release(1, bottomItem->mapToScene(pos).toPoint(), window); // touch point on top item moves to bottom item, but top item should still receive the event QTest::touchEvent(window, touchDevice).press(0, topItem->mapToScene(pos).toPoint(), window); @@ -557,6 +561,7 @@ void tst_qquickwindow::touchEvent_basic() COMPARE_TOUCH_DATA(topItem->lastEvent, makeTouchData(QEvent::TouchUpdate, window, Qt::TouchPointMoved, makeTouchPoint(topItem, topItem->mapFromItem(bottomItem, pos), pos))); topItem->reset(); + QTest::touchEvent(window, touchDevice).release(0, bottomItem->mapToScene(pos).toPoint(), window); // touch point on bottom item moves to top item, but bottom item should still receive the event QTest::touchEvent(window, touchDevice).press(0, bottomItem->mapToScene(pos).toPoint(), window); @@ -567,6 +572,7 @@ void tst_qquickwindow::touchEvent_basic() COMPARE_TOUCH_DATA(bottomItem->lastEvent, makeTouchData(QEvent::TouchUpdate, window, Qt::TouchPointMoved, makeTouchPoint(bottomItem, bottomItem->mapFromItem(topItem, pos), pos))); bottomItem->reset(); + QTest::touchEvent(window, touchDevice).release(0, bottomItem->mapToScene(pos).toPoint(), window); // a single stationary press on an item shouldn't cause an event QTest::touchEvent(window, touchDevice).press(0, topItem->mapToScene(pos).toPoint(), window); @@ -671,6 +677,7 @@ void tst_qquickwindow::touchEvent_propagation() QVERIFY(bottomItem->lastEvent.touchPoints.isEmpty()); COMPARE_TOUCH_DATA(middleItem->lastEvent, makeTouchData(QEvent::TouchBegin, window, Qt::TouchPointPressed, makeTouchPoint(middleItem, middleItem->mapFromItem(topItem, pos)))); + QTest::touchEvent(window, touchDevice).release(0, pointInTopItem, window); // touch top and middle items, middle item should get both events QTest::touchEvent(window, touchDevice).press(0, pointInTopItem, window) @@ -682,6 +689,8 @@ void tst_qquickwindow::touchEvent_propagation() COMPARE_TOUCH_DATA(middleItem->lastEvent, makeTouchData(QEvent::TouchBegin, window, Qt::TouchPointPressed, (QList<QTouchEvent::TouchPoint>() << makeTouchPoint(middleItem, middleItem->mapFromItem(topItem, pos)) << makeTouchPoint(middleItem, pos) ))); + QTest::touchEvent(window, touchDevice).release(0, pointInTopItem, window) + .release(1, pointInMiddleItem, window); middleItem->reset(); // disable middleItem as well @@ -706,6 +715,8 @@ void tst_qquickwindow::touchEvent_propagation() bottomItem->acceptTouchEvents = acceptTouchEvents; bottomItem->setEnabled(enableItem); bottomItem->setVisible(showItem); + QTest::touchEvent(window, touchDevice).release(0, pointInTopItem, window) + .release(1, pointInMiddleItem, window); // no events should be received QTest::touchEvent(window, touchDevice).press(0, pointInTopItem, window) @@ -715,7 +726,9 @@ void tst_qquickwindow::touchEvent_propagation() QVERIFY(topItem->lastEvent.touchPoints.isEmpty()); QVERIFY(middleItem->lastEvent.touchPoints.isEmpty()); QVERIFY(bottomItem->lastEvent.touchPoints.isEmpty()); - + QTest::touchEvent(window, touchDevice).release(0, pointInTopItem, window) + .release(1, pointInMiddleItem, window) + .release(2, pointInBottomItem, window); topItem->reset(); middleItem->reset(); bottomItem->reset(); @@ -741,6 +754,7 @@ void tst_qquickwindow::touchEvent_propagation() COMPARE_TOUCH_DATA(topItem->lastEvent, makeTouchData(QEvent::TouchBegin, window, Qt::TouchPointPressed, makeTouchPoint(topItem, pos))); } + QTest::touchEvent(window, touchDevice).release(0, pointInTopItem, window); delete topItem; delete middleItem; @@ -859,6 +873,8 @@ void tst_qquickwindow::touchEvent_velocity() QWindowSystemInterface::handleTouchEvent(window, touchDeviceWithVelocity, points); QGuiApplication::processEvents(); QQuickTouchUtils::flush(window); + QCOMPARE(item->touchEventCount, 1); + points[0].state = Qt::TouchPointMoved; points[0].area.adjust(5, 5, 5, 5); QVector2D velocity(1.5, 2.5); @@ -891,6 +907,67 @@ void tst_qquickwindow::touchEvent_velocity() delete item; } +void tst_qquickwindow::mergeTouchPointLists_data() +{ + QTest::addColumn<QVector<QQuickItem*>>("list1"); + QTest::addColumn<QVector<QQuickItem*>>("list2"); + QTest::addColumn<QVector<QQuickItem*>>("expected"); + QTest::addColumn<bool>("showItem"); + + // FIXME: do not leak all these items + auto item1 = new QQuickItem(); + auto item2 = new QQuickItem(); + auto item3 = new QQuickItem(); + auto item4 = new QQuickItem(); + auto item5 = new QQuickItem(); + + QTest::newRow("empty") << QVector<QQuickItem*>() << QVector<QQuickItem*>() << QVector<QQuickItem*>(); + QTest::newRow("single list left") + << (QVector<QQuickItem*>() << item1 << item2 << item3) + << QVector<QQuickItem*>() + << (QVector<QQuickItem*>() << item1 << item2 << item3); + QTest::newRow("single list right") + << QVector<QQuickItem*>() + << (QVector<QQuickItem*>() << item1 << item2 << item3) + << (QVector<QQuickItem*>() << item1 << item2 << item3); + QTest::newRow("two lists identical") + << (QVector<QQuickItem*>() << item1 << item2 << item3) + << (QVector<QQuickItem*>() << item1 << item2 << item3) + << (QVector<QQuickItem*>() << item1 << item2 << item3); + QTest::newRow("two lists 1") + << (QVector<QQuickItem*>() << item1 << item2 << item5) + << (QVector<QQuickItem*>() << item3 << item4 << item5) + << (QVector<QQuickItem*>() << item1 << item2 << item3 << item4 << item5); + QTest::newRow("two lists 2") + << (QVector<QQuickItem*>() << item1 << item2 << item5) + << (QVector<QQuickItem*>() << item3 << item4 << item5) + << (QVector<QQuickItem*>() << item1 << item2 << item3 << item4 << item5); + QTest::newRow("two lists 3") + << (QVector<QQuickItem*>() << item1 << item2 << item3) + << (QVector<QQuickItem*>() << item1 << item4 << item5) + << (QVector<QQuickItem*>() << item1 << item2 << item3 << item4 << item5); + QTest::newRow("two lists 4") + << (QVector<QQuickItem*>() << item1 << item3 << item4) + << (QVector<QQuickItem*>() << item2 << item3 << item5) + << (QVector<QQuickItem*>() << item1 << item2 << item3 << item4 << item5); + QTest::newRow("two lists 5") + << (QVector<QQuickItem*>() << item1 << item2 << item4) + << (QVector<QQuickItem*>() << item1 << item3 << item4) + << (QVector<QQuickItem*>() << item1 << item2 << item3 << item4); +} + +void tst_qquickwindow::mergeTouchPointLists() +{ + QFETCH(QVector<QQuickItem*>, list1); + QFETCH(QVector<QQuickItem*>, list2); + QFETCH(QVector<QQuickItem*>, expected); + + QQuickWindow win; + auto windowPrivate = QQuickWindowPrivate::get(&win); + auto targetList = windowPrivate->mergePointerTargets(list1, list2); + QCOMPARE(targetList, expected); +} + void tst_qquickwindow::mouseFromTouch_basic() { // Turn off accepting touch events with acceptTouchEvents. This @@ -1229,13 +1306,14 @@ void tst_qquickwindow::headless() QVERIFY(QTest::qWaitForWindowExposed(window)); QVERIFY(window->isVisible()); - bool threaded = window->openglContext()->thread() != QThread::currentThread(); - + const bool threaded = QQuickWindowPrivate::get(window)->context->thread() != QThread::currentThread(); QSignalSpy initialized(window, SIGNAL(sceneGraphInitialized())); QSignalSpy invalidated(window, SIGNAL(sceneGraphInvalidated())); // Verify that the window is alive and kicking - QVERIFY(window->openglContext() != 0); + QVERIFY(window->isSceneGraphInitialized()); + + const bool isGL = window->rendererInterface()->graphicsApi() == QSGRendererInterface::OpenGL; // Store the visual result QImage originalContent = window->grabWindow(); @@ -1245,15 +1323,16 @@ void tst_qquickwindow::headless() window->releaseResources(); if (threaded) { - QTRY_COMPARE(invalidated.size(), 1); - QVERIFY(!window->openglContext()); + QTRY_VERIFY(invalidated.size() >= 1); + if (isGL) + QVERIFY(!window->isSceneGraphInitialized()); } - +#ifndef QT_NO_OPENGL if (QGuiApplication::platformName() == QLatin1String("windows") && QOpenGLContext::openGLModuleType() == QOpenGLContext::LibGLES) { QSKIP("Crashes on Windows/ANGLE, QTBUG-42967"); } - +#endif // Destroy the native windowing system buffers window->destroy(); QVERIFY(!window->handle()); @@ -1264,7 +1343,8 @@ void tst_qquickwindow::headless() if (threaded) QTRY_COMPARE(initialized.size(), 1); - QVERIFY(window->openglContext() != 0); + + QVERIFY(window->isSceneGraphInitialized()); // Verify that the visual output is the same QImage newContent = window->grabWindow(); @@ -1285,8 +1365,7 @@ void tst_qquickwindow::noUpdateWhenNothingChanges() // the initial expose with a second expose or more. Let these go // through before we let the test continue. QTest::qWait(100); - - if (window.openglContext()->thread() == QGuiApplication::instance()->thread()) { + if (QQuickWindowPrivate::get(&window)->context->thread() == QGuiApplication::instance()->thread()) { QSKIP("Only threaded renderloop implements this feature"); return; } @@ -1593,7 +1672,6 @@ void tst_qquickwindow::hideThenDelete() QSignalSpy *openglDestroyed = 0; QSignalSpy *sgInvalidated = 0; - bool threaded = false; { QQuickWindow window; @@ -1608,9 +1686,13 @@ void tst_qquickwindow::hideThenDelete() window.show(); QTest::qWaitForWindowExposed(&window); - threaded = window.openglContext()->thread() != QThread::currentThread(); + const bool threaded = QQuickWindowPrivate::get(&window)->context->thread() != QGuiApplication::instance()->thread(); + const bool isGL = window.rendererInterface()->graphicsApi() == QSGRendererInterface::OpenGL; +#ifndef QT_NO_OPENGL + if (isGL) + openglDestroyed = new QSignalSpy(window.openglContext(), SIGNAL(aboutToBeDestroyed())); +#endif - openglDestroyed = new QSignalSpy(window.openglContext(), SIGNAL(aboutToBeDestroyed())); sgInvalidated = new QSignalSpy(&window, SIGNAL(sceneGraphInvalidated())); window.hide(); @@ -1618,6 +1700,9 @@ void tst_qquickwindow::hideThenDelete() QTRY_VERIFY(!window.isExposed()); if (threaded) { + if (!isGL) + QSKIP("Skipping persistency verification due to not running with OpenGL"); + if (!persistentSG) { QVERIFY(sgInvalidated->size() > 0); if (!persistentGL) @@ -1632,7 +1717,10 @@ void tst_qquickwindow::hideThenDelete() } QVERIFY(sgInvalidated->size() > 0); - QVERIFY(openglDestroyed->size() > 0); +#ifndef QT_NO_OPENGL + if (openglDestroyed) + QVERIFY(openglDestroyed->size() > 0); +#endif } void tst_qquickwindow::showHideAnimate() @@ -2029,6 +2117,9 @@ void tst_qquickwindow::defaultSurfaceFormat() window.show(); QVERIFY(QTest::qWaitForWindowExposed(&window)); + if (window.rendererInterface()->graphicsApi() != QSGRendererInterface::OpenGL) + QSKIP("Skipping OpenGL context test due to not running with OpenGL"); + const QSurfaceFormat reqFmt = window.requestedFormat(); QCOMPARE(format.swapInterval(), reqFmt.swapInterval()); QCOMPARE(format.redBufferSize(), reqFmt.redBufferSize()); @@ -2037,12 +2128,13 @@ void tst_qquickwindow::defaultSurfaceFormat() QCOMPARE(format.profile(), reqFmt.profile()); QCOMPARE(int(format.options()), int(reqFmt.options())); +#ifndef QT_NO_OPENGL // Depth and stencil should be >= what has been requested. For real. But use // the context since the window's surface format is only partially updated // on most platforms. QVERIFY(window.openglContext()->format().depthBufferSize() >= 16); QVERIFY(window.openglContext()->format().stencilBufferSize() >= 8); - +#endif QSurfaceFormat::setDefaultFormat(savedDefaultFormat); } @@ -2091,7 +2183,7 @@ public: } static int deleted; }; - +#ifndef QT_NO_OPENGL class GlRenderJob : public QRunnable { public: @@ -2113,7 +2205,7 @@ public: QMutex *mutex; QWaitCondition *condition; }; - +#endif int RenderJob::deleted = 0; void tst_qquickwindow::testRenderJob() @@ -2162,25 +2254,29 @@ void tst_qquickwindow::testRenderJob() QTRY_COMPARE(RenderJob::deleted, 1); QCOMPARE(completedJobs.size(), 1); - // Do a synchronized GL job. - GLubyte readPixel[4] = {0, 0, 0, 0}; - GlRenderJob *glJob = new GlRenderJob(readPixel); - if (window.openglContext()->thread() != QThread::currentThread()) { - QMutex mutex; - QWaitCondition condition; - glJob->mutex = &mutex; - glJob->condition = &condition; - mutex.lock(); - window.scheduleRenderJob(glJob, QQuickWindow::NoStage); - condition.wait(&mutex); - mutex.unlock(); - } else { - window.scheduleRenderJob(glJob, QQuickWindow::NoStage); +#ifndef QT_NO_OPENGL + if (window.rendererInterface()->graphicsApi() == QSGRendererInterface::OpenGL) { + // Do a synchronized GL job. + GLubyte readPixel[4] = {0, 0, 0, 0}; + GlRenderJob *glJob = new GlRenderJob(readPixel); + if (window.openglContext()->thread() != QThread::currentThread()) { + QMutex mutex; + QWaitCondition condition; + glJob->mutex = &mutex; + glJob->condition = &condition; + mutex.lock(); + window.scheduleRenderJob(glJob, QQuickWindow::NoStage); + condition.wait(&mutex); + mutex.unlock(); + } else { + window.scheduleRenderJob(glJob, QQuickWindow::NoStage); + } + QCOMPARE(int(readPixel[0]), 255); + QCOMPARE(int(readPixel[1]), 0); + QCOMPARE(int(readPixel[2]), 0); + QCOMPARE(int(readPixel[3]), 255); } - QCOMPARE(int(readPixel[0]), 255); - QCOMPARE(int(readPixel[1]), 0); - QCOMPARE(int(readPixel[2]), 0); - QCOMPARE(int(readPixel[3]), 255); +#endif } // Verify that jobs are deleted when window is not rendered at all @@ -2198,7 +2294,6 @@ void tst_qquickwindow::testRenderJob() class EventCounter : public QQuickRectangle { - Q_OBJECT public: EventCounter(QQuickItem *parent = 0) : QQuickRectangle(parent) @@ -2388,6 +2483,58 @@ void tst_qquickwindow::testHoverTimestamp() QCOMPARE(hoverConsumer->hoverTimestamps.last(), 5UL); } +void tst_qquickwindow::pointerEventTypeAndPointCount() +{ + QPointF localPosition(33, 66); + QPointF scenePosition(133, 166); + QPointF screenPosition(333, 366); + QMouseEvent me(QEvent::MouseButtonPress, localPosition, scenePosition, screenPosition, + Qt::LeftButton, Qt::LeftButton, Qt::NoModifier); + QTouchEvent te(QEvent::TouchBegin, touchDevice, Qt::NoModifier, Qt::TouchPointPressed, + QList<QTouchEvent::TouchPoint>() << QTouchEvent::TouchPoint(1)); + + + QQuickPointerMouseEvent pme; + pme.reset(&me); + QVERIFY(pme.isValid()); + QCOMPARE(pme.asMouseEvent(localPosition), &me); + QVERIFY(pme.asPointerMouseEvent()); + QVERIFY(!pme.asPointerTouchEvent()); + QVERIFY(!pme.asPointerTabletEvent()); +// QVERIFY(!pe->asTabletEvent()); // TODO + QCOMPARE(pme.pointCount(), 1); + QCOMPARE(pme.point(0)->scenePos(), scenePosition); + QCOMPARE(pme.asMouseEvent(localPosition)->localPos(), localPosition); + QCOMPARE(pme.asMouseEvent(localPosition)->screenPos(), screenPosition); + + QQuickPointerTouchEvent pte; + pte.reset(&te); + QVERIFY(pte.isValid()); + QCOMPARE(pte.asTouchEvent(), &te); + QVERIFY(!pte.asPointerMouseEvent()); + QVERIFY(pte.asPointerTouchEvent()); + QVERIFY(!pte.asPointerTabletEvent()); + QVERIFY(pte.asTouchEvent()); +// QVERIFY(!pte.asTabletEvent()); // TODO + QCOMPARE(pte.pointCount(), 1); + QCOMPARE(pte.touchPointById(1)->id(), 1); + QVERIFY(!pte.touchPointById(0)); + + te.setTouchPoints(QList<QTouchEvent::TouchPoint>() << QTouchEvent::TouchPoint(1) << QTouchEvent::TouchPoint(2)); + pte.reset(&te); + QCOMPARE(pte.pointCount(), 2); + QCOMPARE(pte.touchPointById(1)->id(), 1); + QCOMPARE(pte.touchPointById(2)->id(), 2); + QVERIFY(!pte.touchPointById(0)); + + te.setTouchPoints(QList<QTouchEvent::TouchPoint>() << QTouchEvent::TouchPoint(2)); + pte.reset(&te); + QCOMPARE(pte.pointCount(), 1); + QCOMPARE(pte.touchPointById(2)->id(), 2); + QVERIFY(!pte.touchPointById(1)); + QVERIFY(!pte.touchPointById(0)); +} + QTEST_MAIN(tst_qquickwindow) #include "tst_qquickwindow.moc" diff --git a/tests/auto/quick/quick.pro b/tests/auto/quick/quick.pro index 2e43702e7c..c7ba4de86c 100644 --- a/tests/auto/quick/quick.pro +++ b/tests/auto/quick/quick.pro @@ -2,10 +2,20 @@ TEMPLATE = subdirs PUBLICTESTS += \ geometry \ - rendernode \ qquickpixmapcache -qtHaveModule(widgets): PUBLICTESTS += nodes +qtConfig(opengl(es1|es2)?) { + PUBLICTESTS += \ + rendernode + qtHaveModule(widgets): PUBLICTESTS += nodes + + QUICKTESTS += \ + qquickanimatedsprite \ + qquickframebufferobject \ + qquickopenglinfo \ + qquickspritesequence \ + qquickshadereffect +} !cross_compile: PRIVATETESTS += examples @@ -39,7 +49,6 @@ QUICKTESTS = \ qquickaccessible \ qquickanchors \ qquickanimatedimage \ - qquickanimatedsprite \ qquickdynamicpropertyanimation \ qquickborderimage \ qquickwindow \ @@ -48,7 +57,7 @@ QUICKTESTS = \ qquickflickable \ qquickflipable \ qquickfocusscope \ - qquickframebufferobject \ + qquickgraphicsinfo \ qquickgridview \ qquickimage \ qquickitem \ @@ -58,16 +67,13 @@ QUICKTESTS = \ qquickloader \ qquickmousearea \ qquickmultipointtoucharea \ - qquickopenglinfo \ qquickpainteditem \ qquickpathview \ qquickpincharea \ qquickpositioners \ qquickrectangle \ qquickrepeater \ - qquickshadereffect \ qquickshortcut \ - qquickspritesequence \ qquicktext \ qquicktextdocument \ qquicktextedit \ @@ -82,9 +88,9 @@ QUICKTESTS = \ SUBDIRS += $$PUBLICTESTS -!contains(QT_CONFIG, accessibility):QUICKTESTS -= qquickaccessible +!qtConfig(accessibility):QUICKTESTS -= qquickaccessible -contains(QT_CONFIG, private_tests) { +qtConfig(private_tests) { SUBDIRS += $$PRIVATETESTS SUBDIRS += $$QUICKTESTS } diff --git a/tests/auto/quick/rendernode/tst_rendernode.cpp b/tests/auto/quick/rendernode/tst_rendernode.cpp index 249612797b..e0fe2c42fc 100644 --- a/tests/auto/quick/rendernode/tst_rendernode.cpp +++ b/tests/auto/quick/rendernode/tst_rendernode.cpp @@ -66,12 +66,12 @@ private slots: class ClearNode : public QSGRenderNode { public: - virtual StateFlags changedStates() + StateFlags changedStates() const override { return ColorState; } - virtual void render(const RenderState &) + void render(const RenderState *) override { // If clip has been set, scissoring will make sure the right area is cleared. QOpenGLContext::currentContext()->functions()->glClearColor(color.redF(), color.greenF(), color.blueF(), 1.0f); @@ -122,13 +122,13 @@ class MessUpNode : public QSGRenderNode, protected QOpenGLFunctions public: MessUpNode() : initialized(false) { } - virtual StateFlags changedStates() + StateFlags changedStates() const override { return StateFlags(DepthState) | StencilState | ScissorState | ColorState | BlendState - | CullState | ViewportState; + | CullState | ViewportState | RenderTargetState; } - virtual void render(const RenderState &) + void render(const RenderState *) override { if (!initialized) { initializeOpenGLFunctions(); @@ -152,6 +152,9 @@ public: glGetIntegerv(GL_FRONT_FACE, &frontFace); glFrontFace(frontFace == GL_CW ? GL_CCW : GL_CW); glEnable(GL_CULL_FACE); + GLuint fbo; + glGenFramebuffers(1, &fbo); + glBindFramebuffer(GL_FRAMEBUFFER, fbo); } bool initialized; @@ -259,8 +262,8 @@ void tst_rendernode::messUpState() class StateRecordingRenderNode : public QSGRenderNode { public: - StateFlags changedStates() { return StateFlags(-1); } - void render(const RenderState &) { + StateFlags changedStates() const override { return StateFlags(-1); } + void render(const RenderState *) override { matrices[name] = *matrix(); } diff --git a/tests/auto/quick/scenegraph/scenegraph.pro b/tests/auto/quick/scenegraph/scenegraph.pro index 320228bd08..40ff7750cc 100644 --- a/tests/auto/quick/scenegraph/scenegraph.pro +++ b/tests/auto/quick/scenegraph/scenegraph.pro @@ -3,6 +3,7 @@ TARGET = tst_scenegraph SOURCES += tst_scenegraph.cpp include (../../shared/util.pri) +include (../shared/util.pri) macx:CONFIG -= app_bundle diff --git a/tests/auto/quick/scenegraph/tst_scenegraph.cpp b/tests/auto/quick/scenegraph/tst_scenegraph.cpp index 1e46727526..f6d624d871 100644 --- a/tests/auto/quick/scenegraph/tst_scenegraph.cpp +++ b/tests/auto/quick/scenegraph/tst_scenegraph.cpp @@ -28,18 +28,26 @@ #include <qtest.h> +#ifndef QT_NO_OPENGL #include <QOffscreenSurface> #include <QOpenGLContext> #include <QOpenGLFunctions> +#endif #include <QtQuick> #include <QtQml> +#ifndef QT_NO_OPENGL #include <private/qopenglcontext_p.h> +#endif + #include <private/qsgcontext_p.h> #include <private/qsgrenderloop_p.h> #include "../../shared/util.h" +#include "../shared/visualtestutil.h" + +using namespace QQuickVisualTestUtil; class PerPixelRect : public QQuickItem { @@ -97,9 +105,9 @@ private slots: void render_data(); void render(); - +#ifndef QT_NO_OPENGL void hideWithOtherContext(); - +#endif void createTextureFromImage_data(); void createTextureFromImage(); @@ -122,6 +130,7 @@ void tst_SceneGraph::initTestCase() QSGRenderLoop *loop = QSGRenderLoop::instance(); qDebug() << "RenderLoop: " << loop; +#ifndef QT_NO_OPENGL QOpenGLContext context; context.setFormat(loop->sceneGraphContext()->defaultSurfaceFormat()); context.create(); @@ -154,6 +163,7 @@ void tst_SceneGraph::initTestCase() qDebug() << "Broken Mipmap: " << m_brokenMipmapSupport; context.doneCurrent(); +#endif } QQuickView *tst_SceneGraph::createView(const QString &file, QWindow *parent, int x, int y, int w, int h) @@ -169,12 +179,17 @@ QQuickView *tst_SceneGraph::createView(const QString &file, QWindow *parent, int // Assumes the images are opaque white... bool containsSomethingOtherThanWhite(const QImage &image) { - Q_ASSERT(image.format() == QImage::Format_ARGB32_Premultiplied - || image.format() == QImage::Format_RGB32); - int w = image.width(); - int h = image.height(); + QImage img; + if (image.format() != QImage::Format_ARGB32_Premultiplied + || image.format() != QImage::Format_RGB32) + img = image.convertToFormat(QImage::Format_ARGB32_Premultiplied); + else + img = image; + + int w = img.width(); + int h = img.height(); for (int y=0; y<h; ++y) { - const uint *pixels = (const uint *) image.constScanLine(y); + const uint *pixels = (const uint *) img.constScanLine(y); for (int x=0; x<w; ++x) if (pixels[x] != 0xffffffff) return true; @@ -182,44 +197,6 @@ bool containsSomethingOtherThanWhite(const QImage &image) return false; } -// When running on native Nvidia graphics cards on linux, the -// distance field glyph pixels have a measurable, but not visible -// pixel error. Use a custom compare function to avoid -// -// This was GT-216 with the ubuntu "nvidia-319" driver package. -// llvmpipe does not show the same issue. -// -bool compareImages(const QImage &ia, const QImage &ib) -{ - if (ia.size() != ib.size()) - qDebug() << "images are of different size" << ia.size() << ib.size(); - Q_ASSERT(ia.size() == ib.size()); - Q_ASSERT(ia.format() == ib.format()); - - int w = ia.width(); - int h = ia.height(); - const int tolerance = 5; - for (int y=0; y<h; ++y) { - const uint *as= (const uint *) ia.constScanLine(y); - const uint *bs= (const uint *) ib.constScanLine(y); - for (int x=0; x<w; ++x) { - uint a = as[x]; - uint b = bs[x]; - - // No tolerance for error in the alpha. - if ((a & 0xff000000) != (b & 0xff000000)) - return false; - if (qAbs(qRed(a) - qRed(b)) > tolerance) - return false; - if (qAbs(qRed(a) - qRed(b)) > tolerance) - return false; - if (qAbs(qRed(a) - qRed(b)) > tolerance) - return false; - } - } - return true; -} - void tst_SceneGraph::manyWindows_data() { QTest::addColumn<QString>("file"); @@ -245,24 +222,26 @@ void tst_SceneGraph::manyWindows_data() QTest::newRow("rects,subwindow,sharing") << QStringLiteral("manyWindows_rects.qml") << false << true; } +#ifndef QT_NO_OPENGL struct ShareContextResetter { public: ~ShareContextResetter() { qt_gl_set_global_share_context(0); } }; +#endif void tst_SceneGraph::manyWindows() { QFETCH(QString, file); QFETCH(bool, toplevel); QFETCH(bool, shared); - +#ifndef QT_NO_OPENGL QOpenGLContext sharedGLContext; ShareContextResetter cleanup; // To avoid dangling pointer in case of test-failure. if (shared) { QVERIFY(sharedGLContext.create()); qt_gl_set_global_share_context(&sharedGLContext); } - +#endif QScopedPointer<QWindow> parent; if (!toplevel) { parent.reset(new QWindow()); @@ -451,6 +430,13 @@ void tst_SceneGraph::render_data() void tst_SceneGraph::render() { + QQuickView dummy; + dummy.show(); + QTest::qWaitForWindowExposed(&dummy); + if (dummy.rendererInterface()->graphicsApi() != QSGRendererInterface::OpenGL) + QSKIP("Skipping complex rendering tests due to not running with OpenGL"); + dummy.hide(); + QFETCH(QString, file); QFETCH(QList<Sample>, baseStage); QFETCH(QList<Sample>, finalStage); @@ -493,6 +479,7 @@ void tst_SceneGraph::render() } } +#ifndef QT_NO_OPENGL // Testcase for QTBUG-34898. We make another context current on another surface // in the GUI thread and hide the QQuickWindow while the other context is // current on the other window. @@ -513,6 +500,9 @@ void tst_SceneGraph::hideWithOtherContext() view.show(); QVERIFY(QTest::qWaitForWindowExposed(&view)); + if (view.rendererInterface()->graphicsApi() != QSGRendererInterface::OpenGL) + QSKIP("Skipping OpenGL context test due to not running with OpenGL"); + renderingOnMainThread = view.openglContext()->thread() == QGuiApplication::instance()->thread(); // Make the local context current on the local window... @@ -525,6 +515,7 @@ void tst_SceneGraph::hideWithOtherContext() // GL calls to a new frame (see QOpenGLContext docs). QVERIFY(!renderingOnMainThread || QOpenGLContext::currentContext() != &context); } +#endif void tst_SceneGraph::createTextureFromImage_data() { @@ -550,6 +541,10 @@ void tst_SceneGraph::createTextureFromImage() QFETCH(bool, expectedAlpha); QQuickView view; + view.show(); + QTest::qWaitForWindowExposed(&view); + QTRY_VERIFY(view.isSceneGraphInitialized()); + QScopedPointer<QSGTexture> texture(view.createTextureFromImage(image, (QQuickWindow::CreateTextureOptions) flags)); QCOMPARE(texture->hasAlphaChannel(), expectedAlpha); } diff --git a/tests/auto/quick/shared/visualtestutil.cpp b/tests/auto/quick/shared/visualtestutil.cpp index 3e18c83ee2..eabfe5368b 100644 --- a/tests/auto/quick/shared/visualtestutil.cpp +++ b/tests/auto/quick/shared/visualtestutil.cpp @@ -61,3 +61,38 @@ void QQuickVisualTestUtil::dumpTree(QQuickItem *parent, int depth) } } +// A custom compare function to avoid issues such as: +// When running on native Nvidia graphics cards on linux, the +// distance field glyph pixels have a measurable, but not visible +// pixel error. This was GT-216 with the ubuntu "nvidia-319" driver package. +// llvmpipe does not show the same issue. +bool QQuickVisualTestUtil::compareImages(const QImage &ia, const QImage &ib) +{ + if (ia.size() != ib.size()) + qDebug() << "images are of different size" << ia.size() << ib.size(); + Q_ASSERT(ia.size() == ib.size()); + Q_ASSERT(ia.format() == ib.format()); + + int w = ia.width(); + int h = ia.height(); + const int tolerance = 5; + for (int y=0; y<h; ++y) { + const uint *as= (const uint *) ia.constScanLine(y); + const uint *bs= (const uint *) ib.constScanLine(y); + for (int x=0; x<w; ++x) { + uint a = as[x]; + uint b = bs[x]; + + // No tolerance for error in the alpha. + if ((a & 0xff000000) != (b & 0xff000000)) + return false; + if (qAbs(qRed(a) - qRed(b)) > tolerance) + return false; + if (qAbs(qRed(a) - qRed(b)) > tolerance) + return false; + if (qAbs(qRed(a) - qRed(b)) > tolerance) + return false; + } + } + return true; +} diff --git a/tests/auto/quick/shared/visualtestutil.h b/tests/auto/quick/shared/visualtestutil.h index 2b377a4bab..2daf86cd83 100644 --- a/tests/auto/quick/shared/visualtestutil.h +++ b/tests/auto/quick/shared/visualtestutil.h @@ -96,6 +96,8 @@ namespace QQuickVisualTestUtil items << qobject_cast<QQuickItem*>(findItem<T>(parent, objectName, indexes[i])); return items; } + + bool compareImages(const QImage &ia, const QImage &ib); } #define QQUICK_VERIFY_POLISH(item) \ diff --git a/tests/auto/quick/touchmouse/data/touchpointdeliveryorder.qml b/tests/auto/quick/touchmouse/data/touchpointdeliveryorder.qml new file mode 100644 index 0000000000..9f67c226a0 --- /dev/null +++ b/tests/auto/quick/touchmouse/data/touchpointdeliveryorder.qml @@ -0,0 +1,39 @@ +import QtQuick 2.0 +import Qt.test 1.0 + +Rectangle { + id: root + + width: 600 + height: 400 + + EventItem { + objectName: "background" + width: 600 + height: 400 + Rectangle { anchors.fill: parent; color: "lightsteelblue" } + + EventItem { + objectName: "left" + width: 300 + height: 300 + Rectangle { anchors.fill: parent; color: "yellow" } + } + + EventItem { + objectName: "right" + x: 300 + width: 300 + height: 300 + Rectangle { anchors.fill: parent; color: "green" } + } + + EventItem { + objectName: "middle" + x: 150 + width: 300 + height: 300 + Rectangle { anchors.fill: parent; color: "blue" } + } + } +} diff --git a/tests/auto/quick/touchmouse/touchmouse.pro b/tests/auto/quick/touchmouse/touchmouse.pro index 0df9bc53d3..49818bb399 100644 --- a/tests/auto/quick/touchmouse/touchmouse.pro +++ b/tests/auto/quick/touchmouse/touchmouse.pro @@ -1,7 +1,7 @@ CONFIG += testcase TARGET = tst_touchmouse -QT += core-private gui-private qml-private quick-private testlib +QT += core-private qml-private quick-private testlib macx:CONFIG -= app_bundle diff --git a/tests/auto/quick/touchmouse/tst_touchmouse.cpp b/tests/auto/quick/touchmouse/tst_touchmouse.cpp index 72cc76a855..309c01dcdc 100644 --- a/tests/auto/quick/touchmouse/tst_touchmouse.cpp +++ b/tests/auto/quick/touchmouse/tst_touchmouse.cpp @@ -33,13 +33,12 @@ #include <QtQuick/qquickview.h> #include <QtQuick/qquickitem.h> +#include <QtQuick/private/qquickevents_p_p.h> #include <QtQuick/private/qquickmousearea_p.h> #include <QtQuick/private/qquickmultipointtoucharea_p.h> #include <QtQuick/private/qquickpincharea_p.h> #include <QtQuick/private/qquickflickable_p.h> -#include <qpa/qwindowsysteminterface.h> - -#include <private/qquickwindow_p.h> +#include <QtQuick/private/qquickwindow_p.h> #include <QtQml/qqmlengine.h> #include <QtQml/qqmlproperty.h> @@ -66,15 +65,22 @@ struct Event class EventItem : public QQuickItem { Q_OBJECT + +Q_SIGNALS: + void onTouchEvent(QQuickItem *receiver); + public: EventItem(QQuickItem *parent = 0) : QQuickItem(parent), acceptMouse(false), acceptTouch(false), filterTouch(false) - {} + { + setAcceptedMouseButtons(Qt::LeftButton); + } void touchEvent(QTouchEvent *event) { eventList.append(Event(event->type(), event->touchPoints())); event->setAccepted(acceptTouch); + emit onTouchEvent(this); } void mousePressEvent(QMouseEvent *event) { @@ -132,7 +138,7 @@ class tst_TouchMouse : public QQmlDataTest Q_OBJECT public: tst_TouchMouse() - :device(0) + :device(QTest::createTouchDevice()) {} private slots: @@ -145,6 +151,7 @@ private slots: void mouseOverTouch(); void buttonOnFlickable(); + void buttonOnDelayedPressFlickable_data(); void buttonOnDelayedPressFlickable(); void buttonOnTouch(); @@ -155,6 +162,7 @@ private slots: void tapOnDismissiveTopMouseAreaClicksBottomOne(); void touchGrabCausesMouseUngrab(); + void touchPointDeliveryOrder(); void hoverEnabled(); @@ -191,11 +199,6 @@ void tst_TouchMouse::initTestCase() QQmlDataTest::initTestCase(); qmlRegisterType<EventItem>("Qt.test", 1, 0, "EventItem"); - if (!device) { - device = new QTouchDevice; - device->setType(QTouchDevice::TouchScreen); - QWindowSystemInterface::registerTouchDevice(device); - } } void tst_TouchMouse::simpleTouchEvent() @@ -217,15 +220,17 @@ void tst_TouchMouse::simpleTouchEvent() p1 = QPoint(20, 20); QTest::touchEvent(window, device).press(0, p1, window); QQuickTouchUtils::flush(window); - QCOMPARE(eventItem1->eventList.size(), 1); + // Get a touch and then mouse event offered + QCOMPARE(eventItem1->eventList.size(), 2); QCOMPARE(eventItem1->eventList.at(0).type, QEvent::TouchBegin); p1 += QPoint(10, 0); QTest::touchEvent(window, device).move(0, p1, window); QQuickTouchUtils::flush(window); - QCOMPARE(eventItem1->eventList.size(), 1); + // Not accepted, no updates + QCOMPARE(eventItem1->eventList.size(), 2); QTest::touchEvent(window, device).release(0, p1, window); QQuickTouchUtils::flush(window); - QCOMPARE(eventItem1->eventList.size(), 1); + QCOMPARE(eventItem1->eventList.size(), 2); eventItem1->eventList.clear(); // Accept touch @@ -256,8 +261,7 @@ void tst_TouchMouse::simpleTouchEvent() QCOMPARE(eventItem1->eventList.size(), 2); QCOMPARE(eventItem1->eventList.at(0).type, QEvent::TouchBegin); QCOMPARE(eventItem1->eventList.at(1).type, QEvent::MouseButtonPress); - QQuickWindowPrivate *windowPriv = QQuickWindowPrivate::get(window); - QCOMPARE(windowPriv->mouseGrabberItem, eventItem1); + QCOMPARE(window->mouseGrabberItem(), eventItem1); QPoint localPos = eventItem1->mapFromScene(p1).toPoint(); QPoint globalPos = window->mapToGlobal(p1); @@ -292,17 +296,16 @@ void tst_TouchMouse::simpleTouchEvent() p1 = QPoint(20, 20); QTest::touchEvent(window, device).press(0, p1, window); QQuickTouchUtils::flush(window); - QCOMPARE(eventItem1->eventList.size(), 3); + QCOMPARE(eventItem1->eventList.size(), 2); QCOMPARE(eventItem1->eventList.at(0).type, QEvent::TouchBegin); QCOMPARE(eventItem1->eventList.at(1).type, QEvent::MouseButtonPress); - QCOMPARE(eventItem1->eventList.at(2).type, QEvent::UngrabMouse); p1 += QPoint(10, 0); QTest::touchEvent(window, device).move(0, p1, window); QQuickTouchUtils::flush(window); - QCOMPARE(eventItem1->eventList.size(), 3); + QCOMPARE(eventItem1->eventList.size(), 2); QTest::touchEvent(window, device).release(0, p1, window); QQuickTouchUtils::flush(window); - QCOMPARE(eventItem1->eventList.size(), 3); + QCOMPARE(eventItem1->eventList.size(), 2); eventItem1->eventList.clear(); // wait to avoid getting a double click event @@ -579,8 +582,9 @@ void tst_TouchMouse::buttonOnFlickable() QQuickWindowPrivate *windowPriv = QQuickWindowPrivate::get(window); QCOMPARE(windowPriv->touchMouseId, 0); - QCOMPARE(windowPriv->itemForTouchPointId[0], eventItem1); - QCOMPARE(windowPriv->mouseGrabberItem, eventItem1); + auto pointerEvent = QQuickPointerDevice::touchDevices().at(0)->pointerEvent(); + QCOMPARE(pointerEvent->point(0)->grabber(), eventItem1); + QCOMPARE(window->mouseGrabberItem(), eventItem1); p1 += QPoint(0, -10); QPoint p2 = p1 + QPoint(0, -10); @@ -598,9 +602,9 @@ void tst_TouchMouse::buttonOnFlickable() QCOMPARE(eventItem1->eventList.at(2).type, QEvent::TouchUpdate); QCOMPARE(eventItem1->eventList.at(3).type, QEvent::MouseMove); - QCOMPARE(windowPriv->mouseGrabberItem, flickable); + QCOMPARE(window->mouseGrabberItem(), flickable); QCOMPARE(windowPriv->touchMouseId, 0); - QCOMPARE(windowPriv->itemForTouchPointId[0], flickable); + QCOMPARE(pointerEvent->point(0)->grabber(), flickable); QVERIFY(flickable->isMovingVertically()); QTest::touchEvent(window, device).release(0, p3, window); @@ -608,11 +612,25 @@ void tst_TouchMouse::buttonOnFlickable() delete window; } +void tst_TouchMouse::buttonOnDelayedPressFlickable_data() +{ + QTest::addColumn<bool>("scrollBeforeDelayIsOver"); + + // the item should never see the event, + // due to the pressDelay which never delivers if we start moving + QTest::newRow("scroll before press delay is over") << true; + + // wait until the "button" sees the press but then + // start moving: the button gets a press and cancel event + QTest::newRow("scroll after press delay is over") << false; +} + void tst_TouchMouse::buttonOnDelayedPressFlickable() { // flickable - height 500 / 1000 // - eventItem1 y: 100, height 100 // - eventItem2 y: 300, height 100 + QFETCH(bool, scrollBeforeDelayIsOver); qApp->setAttribute(Qt::AA_SynthesizeMouseForUnhandledTouchEvents, true); filteredEventList.clear(); @@ -631,7 +649,8 @@ void tst_TouchMouse::buttonOnDelayedPressFlickable() window->installEventFilter(this); - flickable->setPressDelay(60); + // wait 600 ms before letting the child see the press event + flickable->setPressDelay(600); // should a mouse area button be clickable on top of flickable? yes :) EventItem *eventItem1 = window->rootObject()->findChild<EventItem*>("eventItem1"); @@ -647,25 +666,23 @@ void tst_TouchMouse::buttonOnDelayedPressFlickable() // wait to avoid getting a double click event QTest::qWait(qApp->styleHints()->mouseDoubleClickInterval() + 10); + QQuickWindowPrivate *windowPriv = QQuickWindowPrivate::get(window); + QCOMPARE(windowPriv->touchMouseId, -1); // no grabber - // check that flickable moves - mouse button - QCOMPARE(eventItem1->eventList.size(), 0); + // touch press QPoint p1 = QPoint(10, 110); QTest::touchEvent(window, device).press(0, p1, window); QQuickTouchUtils::flush(window); - // Flickable initially steals events - QCOMPARE(eventItem1->eventList.size(), 0); - // but we'll get the delayed mouse press after a delay - QTRY_COMPARE(eventItem1->eventList.size(), 1); - QCOMPARE(eventItem1->eventList.at(0).type, QEvent::MouseButtonPress); - QCOMPARE(filteredEventList.count(), 1); - // eventItem1 should have the mouse grab, and have moved the itemForTouchPointId - // for the touchMouseId to the new grabber. - QQuickWindowPrivate *windowPriv = QQuickWindowPrivate::get(window); - QCOMPARE(windowPriv->touchMouseId, 0); - QCOMPARE(windowPriv->itemForTouchPointId[0], eventItem1); - QCOMPARE(windowPriv->mouseGrabberItem, eventItem1); + if (scrollBeforeDelayIsOver) { + // no events, the flickable got scrolled, the button sees nothing + QCOMPARE(eventItem1->eventList.size(), 0); + } else { + // wait until the button sees the press + QTRY_COMPARE(eventItem1->eventList.size(), 1); + QCOMPARE(eventItem1->eventList.at(0).type, QEvent::MouseButtonPress); + QCOMPARE(filteredEventList.count(), 1); + } p1 += QPoint(0, -10); QPoint p2 = p1 + QPoint(0, -10); @@ -677,20 +694,35 @@ void tst_TouchMouse::buttonOnDelayedPressFlickable() QQuickTouchUtils::flush(window); QTest::touchEvent(window, device).move(0, p3, window); QQuickTouchUtils::flush(window); - QVERIFY(flickable->isMovingVertically()); + QTRY_VERIFY(flickable->isMovingVertically()); + + if (scrollBeforeDelayIsOver) { + QCOMPARE(eventItem1->eventList.size(), 0); + QCOMPARE(filteredEventList.count(), 0); + } else { + // see at least press, move and ungrab + QTRY_VERIFY(eventItem1->eventList.size() > 2); + QCOMPARE(eventItem1->eventList.at(0).type, QEvent::MouseButtonPress); + QCOMPARE(eventItem1->eventList.last().type, QEvent::UngrabMouse); + QCOMPARE(filteredEventList.count(), 1); + } // flickable should have the mouse grab, and have moved the itemForTouchPointId // for the touchMouseId to the new grabber. - QCOMPARE(windowPriv->mouseGrabberItem, flickable); + QCOMPARE(window->mouseGrabberItem(), flickable); QCOMPARE(windowPriv->touchMouseId, 0); - QCOMPARE(windowPriv->itemForTouchPointId[0], flickable); + auto pointerEvent = QQuickPointerDevice::touchDevices().at(0)->pointerEvent(); + QCOMPARE(pointerEvent->point(0)->grabber(), flickable); QTest::touchEvent(window, device).release(0, p3, window); QQuickTouchUtils::flush(window); // We should not have received any synthesised mouse events from Qt gui, // just the delayed press. - QCOMPARE(filteredEventList.count(), 1); + if (scrollBeforeDelayIsOver) + QCOMPARE(filteredEventList.count(), 0); + else + QCOMPARE(filteredEventList.count(), 1); delete window; } @@ -1097,9 +1129,7 @@ void tst_TouchMouse::mouseOnFlickableOnPinch() pinchSequence.move(0, p, window).commit(); QQuickTouchUtils::flush(window); - QQuickWindowPrivate *windowPriv = QQuickWindowPrivate::get(window); - qDebug() << "Mouse Grabber: " << windowPriv->mouseGrabberItem << " itemForTouchPointId: " << windowPriv->itemForTouchPointId; - QCOMPARE(windowPriv->mouseGrabberItem, flickable); + QCOMPARE(window->mouseGrabberItem(), flickable); // Add a second finger, this should lead to stealing p1 = QPoint(40, 100); @@ -1229,6 +1259,105 @@ void tst_TouchMouse::touchGrabCausesMouseUngrab() delete window; } +void tst_TouchMouse::touchPointDeliveryOrder() +{ + // Touch points should be first delivered to the item under the primary finger + QScopedPointer<QQuickView> window(createView()); + + window->setSource(testFileUrl("touchpointdeliveryorder.qml")); + /* + The items are positioned from left to right: + | background | + | left | + | | right | + | middle | + 0 150 300 450 600 + */ + QPoint pLeft = QPoint(100, 100); + QPoint pRight = QPoint(500, 100); + QPoint pLeftMiddle = QPoint(200, 100); + QPoint pRightMiddle = QPoint(350, 100); + + window->show(); + QVERIFY(QTest::qWaitForWindowExposed(window.data())); + + QVector<QQuickItem*> events; + EventItem *background = window->rootObject()->findChild<EventItem*>("background"); + EventItem *left = window->rootObject()->findChild<EventItem*>("left"); + EventItem *middle = window->rootObject()->findChild<EventItem*>("middle"); + EventItem *right = window->rootObject()->findChild<EventItem*>("right"); + QVERIFY(background); + QVERIFY(left); + QVERIFY(middle); + QVERIFY(right); + connect(background, &EventItem::onTouchEvent, [&events](QQuickItem* receiver){ events.append(receiver); }); + connect(left, &EventItem::onTouchEvent, [&events](QQuickItem* receiver){ events.append(receiver); }); + connect(middle, &EventItem::onTouchEvent, [&events](QQuickItem* receiver){ events.append(receiver); }); + connect(right, &EventItem::onTouchEvent, [&events](QQuickItem* receiver){ events.append(receiver); }); + + QTest::touchEvent(window.data(), device).press(0, pLeft, window.data()); + QQuickTouchUtils::flush(window.data()); + + // Touch on left, then background + QCOMPARE(events.size(), 2); + QCOMPARE(events.at(0), left); + QCOMPARE(events.at(1), background); + events.clear(); + + // New press events are deliverd first, the stationary point was not accepted, thus it doesn't get delivered + QTest::touchEvent(window.data(), device).stationary(0).press(1, pRightMiddle, window.data()); + QQuickTouchUtils::flush(window.data()); + QCOMPARE(events.size(), 3); + QCOMPARE(events.at(0), middle); + QCOMPARE(events.at(1), right); + QCOMPARE(events.at(2), background); + events.clear(); + + QTest::touchEvent(window.data(), device).release(0, pLeft, window.data()).release(1, pRightMiddle, window.data()); + QQuickTouchUtils::flush(window.data()); + QCOMPARE(events.size(), 0); // no accepted events + + // Two presses, the first point should come first + QTest::touchEvent(window.data(), device).press(0, pLeft, window.data()).press(1, pRight, window.data()); + QQuickTouchUtils::flush(window.data()); + QCOMPARE(events.size(), 3); + QCOMPARE(events.at(0), left); + QCOMPARE(events.at(1), right); + QCOMPARE(events.at(2), background); + QTest::touchEvent(window.data(), device).release(0, pLeft, window.data()).release(1, pRight, window.data()); + events.clear(); + + // Again, pressing right first + QTest::touchEvent(window.data(), device).press(0, pRight, window.data()).press(1, pLeft, window.data()); + QQuickTouchUtils::flush(window.data()); + QCOMPARE(events.size(), 3); + QCOMPARE(events.at(0), right); + QCOMPARE(events.at(1), left); + QCOMPARE(events.at(2), background); + QTest::touchEvent(window.data(), device).release(0, pRight, window.data()).release(1, pLeft, window.data()); + events.clear(); + + // Two presses, both hitting the middle item on top, then branching left and right, then bottom + // Each target should be offered the events exactly once, middle first, left must come before right (id 0) + QTest::touchEvent(window.data(), device).press(0, pLeftMiddle, window.data()).press(1, pRightMiddle, window.data()); + QCOMPARE(events.size(), 4); + QCOMPARE(events.at(0), middle); + QCOMPARE(events.at(1), left); + QCOMPARE(events.at(2), right); + QCOMPARE(events.at(3), background); + QTest::touchEvent(window.data(), device).release(0, pLeftMiddle, window.data()).release(1, pRightMiddle, window.data()); + events.clear(); + + QTest::touchEvent(window.data(), device).press(0, pRightMiddle, window.data()).press(1, pLeftMiddle, window.data()); + qDebug() << events; + QCOMPARE(events.size(), 4); + QCOMPARE(events.at(0), middle); + QCOMPARE(events.at(1), right); + QCOMPARE(events.at(2), left); + QCOMPARE(events.at(3), background); + QTest::touchEvent(window.data(), device).release(0, pRightMiddle, window.data()).release(1, pLeftMiddle, window.data()); +} + void tst_TouchMouse::hoverEnabled() { // QTouchDevice *device = new QTouchDevice; @@ -1276,8 +1405,8 @@ void tst_TouchMouse::hoverEnabled() // ------------------------- Touch click on mouseArea1 QTest::touchEvent(window, device).press(0, p1, window); - QVERIFY(enterSpy1.count() == 1); - QVERIFY(enterSpy2.count() == 0); + QCOMPARE(enterSpy1.count(), 1); + QCOMPARE(enterSpy2.count(), 0); QVERIFY(mouseArea1->pressed()); QVERIFY(mouseArea1->hovered()); QVERIFY(!mouseArea2->hovered()); @@ -1288,33 +1417,36 @@ void tst_TouchMouse::hoverEnabled() QVERIFY(!mouseArea2->hovered()); // ------------------------- Touch click on mouseArea2 + if (QGuiApplication::platformName().compare(QLatin1String("xcb"), Qt::CaseInsensitive) == 0) + QSKIP("hover can be momentarily inconsistent on X11, depending on timing of flushFrameSynchronousEvents with touch and mouse movements (QTBUG-55350)"); + QTest::touchEvent(window, device).press(0, p2, window); QVERIFY(mouseArea1->hovered()); QVERIFY(mouseArea2->hovered()); QVERIFY(mouseArea2->pressed()); - QVERIFY(enterSpy1.count() == 1); - QVERIFY(enterSpy2.count() == 1); + QCOMPARE(enterSpy1.count(), 1); + QCOMPARE(enterSpy2.count(), 1); QTest::touchEvent(window, device).release(0, p2, window); QVERIFY(clickSpy2.count() == 1); QVERIFY(mouseArea1->hovered()); QVERIFY(!mouseArea2->hovered()); - QVERIFY(exitSpy1.count() == 0); - QVERIFY(exitSpy2.count() == 1); + QCOMPARE(exitSpy1.count(), 0); + QCOMPARE(exitSpy2.count(), 1); // ------------------------- Another touch click on mouseArea1 QTest::touchEvent(window, device).press(0, p1, window); - QVERIFY(enterSpy1.count() == 1); - QVERIFY(enterSpy2.count() == 1); + QCOMPARE(enterSpy1.count(), 1); + QCOMPARE(enterSpy2.count(), 1); QVERIFY(mouseArea1->pressed()); QVERIFY(mouseArea1->hovered()); QVERIFY(!mouseArea2->hovered()); QTest::touchEvent(window, device).release(0, p1, window); - QVERIFY(clickSpy1.count() == 2); + QCOMPARE(clickSpy1.count(), 2); QVERIFY(mouseArea1->hovered()); QVERIFY(!mouseArea1->pressed()); QVERIFY(!mouseArea2->hovered()); |