diff options
Diffstat (limited to 'user/qt5-qtdeclarative/kde-lts.patch')
-rw-r--r-- | user/qt5-qtdeclarative/kde-lts.patch | 2807 |
1 files changed, 1524 insertions, 1283 deletions
diff --git a/user/qt5-qtdeclarative/kde-lts.patch b/user/qt5-qtdeclarative/kde-lts.patch index c09ed5232..8d1fcd36a 100644 --- a/user/qt5-qtdeclarative/kde-lts.patch +++ b/user/qt5-qtdeclarative/kde-lts.patch @@ -1,152 +1,7 @@ -From eb1025d7808f04e3f114b08c86a5e680b2d18010 Mon Sep 17 00:00:00 2001 -From: Albert Astals Cid <albert.astals.cid@kdab.com> -Date: Fri, 21 May 2021 13:30:41 +0200 -Subject: [PATCH 01/19] Give a warning when StyledText encounters a non - supported entity - -Pick-to: 6.1 5.15 -Change-Id: Iea8bdf25542cd404ee71141467ac1f1398a7d0df -Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io> -(cherry picked from commit 8cd43e370040e23fcbd03ad64969e683055bd7d0) ---- - src/quick/util/qquickstyledtext.cpp | 4 ++++ - 1 file changed, 4 insertions(+) - -diff --git a/src/quick/util/qquickstyledtext.cpp b/src/quick/util/qquickstyledtext.cpp -index 660852ba83..d531fc9205 100644 ---- a/src/quick/util/qquickstyledtext.cpp -+++ b/src/quick/util/qquickstyledtext.cpp -@@ -46,6 +46,8 @@ - #include "qquickstyledtext_p.h" - #include <QQmlContext> - -+Q_LOGGING_CATEGORY(lcStyledText, "qt.quick.styledtext") -+ - /* - QQuickStyledText supports few tags: - -@@ -566,6 +568,8 @@ void QQuickStyledTextPrivate::parseEntity(const QChar *&ch, const QString &textI - textOut += QChar(34); - else if (entity == QLatin1String("nbsp")) - textOut += QChar(QChar::Nbsp); -+ else -+ qCWarning(lcStyledText) << "StyledText doesn't support entity" << entity; - return; - } else if (*ch == QLatin1Char(' ')) { - QStringRef entity(&textIn, entityStart - 1, entityLength + 1); --- -2.36.0 - -From ba07a40a2afacfb57ddb8f7cb4cc90a39560f17d Mon Sep 17 00:00:00 2001 -From: Antonio Rojas <arojas@archlinux.org> -Date: Sun, 23 May 2021 14:32:46 +0200 -Subject: [PATCH 02/19] Add missing limits include to fix build with GCC 11 - -This is not required for Qt 6, since it is indirectly pulled via -qanystrigview.h, but it is for Qt 5 (where qanystrigview does -not exist) and, in any case, it is good to declare all used headers -and not rely on them being implicitly pulled. - -Pick-to: 6.1 5.15 -Change-Id: I97606ea493e723006759608b7d4c4f00632f340c -Reviewed-by: Albert Astals Cid <albert.astals.cid@kdab.com> -(cherry picked from commit 367293b18ab0d0a0432c1c8ce445fee052e5eee5) ---- - src/qmldebug/qqmlprofilerevent_p.h | 1 + - 1 file changed, 1 insertion(+) - -diff --git a/src/qmldebug/qqmlprofilerevent_p.h b/src/qmldebug/qqmlprofilerevent_p.h -index a7e37d1964..01b2f58f16 100644 ---- a/src/qmldebug/qqmlprofilerevent_p.h -+++ b/src/qmldebug/qqmlprofilerevent_p.h -@@ -48,6 +48,7 @@ - #include <QtCore/qmetatype.h> - - #include <initializer_list> -+#include <limits> - #include <type_traits> - - // --- -2.36.0 - -From eb9ebe3815ac100d4ab3b3a708f691a1dde270bf Mon Sep 17 00:00:00 2001 -From: Albert Astals Cid <albert.astals.cid@kdab.com> -Date: Fri, 21 May 2021 13:17:15 +0200 -Subject: [PATCH 03/19] Document that StyledText also supports and - " - -Change-Id: I1715f8ae8ec8d0fbaf6dbe2b8663cc169da663cd -Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io> -(cherry picked from commit 5848c081c094a66e024493fc1e5c2569e06f73b6) ---- - src/quick/items/qquicktext.cpp | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/src/quick/items/qquicktext.cpp b/src/quick/items/qquicktext.cpp -index 6230186933..c1571fc6f5 100644 ---- a/src/quick/items/qquicktext.cpp -+++ b/src/quick/items/qquicktext.cpp -@@ -2168,7 +2168,7 @@ void QQuickText::resetMaximumLineCount() - <img src="" align="top,middle,bottom" width="" height=""> - inline images - <ol type="">, <ul type=""> and <li> - ordered and unordered lists - <pre></pre> - preformatted -- > < & -+ > < & " - \endcode - - \c Text.StyledText parser is strict, requiring tags to be correctly nested. --- -2.36.0 - -From 0aea240ef6d78989ef16ea1d41e161c641c2667c Mon Sep 17 00:00:00 2001 -From: Albert Astals Cid <albert.astals.cid@kdab.com> -Date: Fri, 21 May 2021 13:42:35 +0200 -Subject: [PATCH 04/19] Support ' in styled text - -Pick-to: 6.1 5.15 -Change-Id: I4a8db963e52a7899ab1796f9a560e8029cc1c929 -Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io> -Reviewed-by: Eskil Abrahamsen Blomfeldt <eskil.abrahamsen-blomfeldt@qt.io> -(cherry picked from commit 96b528efcba1226d2980828d1255160bdceae4cf) ---- - src/quick/items/qquicktext.cpp | 2 +- - src/quick/util/qquickstyledtext.cpp | 2 ++ - 2 files changed, 3 insertions(+), 1 deletion(-) - -diff --git a/src/quick/items/qquicktext.cpp b/src/quick/items/qquicktext.cpp -index c1571fc6f5..e823ca1095 100644 ---- a/src/quick/items/qquicktext.cpp -+++ b/src/quick/items/qquicktext.cpp -@@ -2168,7 +2168,7 @@ void QQuickText::resetMaximumLineCount() - <img src="" align="top,middle,bottom" width="" height=""> - inline images - <ol type="">, <ul type=""> and <li> - ordered and unordered lists - <pre></pre> - preformatted -- > < & " -+ > < & " ' - \endcode - - \c Text.StyledText parser is strict, requiring tags to be correctly nested. -diff --git a/src/quick/util/qquickstyledtext.cpp b/src/quick/util/qquickstyledtext.cpp -index d531fc9205..a25af90414 100644 ---- a/src/quick/util/qquickstyledtext.cpp -+++ b/src/quick/util/qquickstyledtext.cpp -@@ -564,6 +564,8 @@ void QQuickStyledTextPrivate::parseEntity(const QChar *&ch, const QString &textI - textOut += QChar(60); - else if (entity == QLatin1String("amp")) - textOut += QChar(38); -+ else if (entity == QLatin1String("apos")) -+ textOut += QChar(39); - else if (entity == QLatin1String("quot")) - textOut += QChar(34); - else if (entity == QLatin1String("nbsp")) --- -2.36.0 - -From bdf7658d89e1df55ded318432d4412dbf1d5d0f9 Mon Sep 17 00:00:00 2001 +From 70c3f2cdc7b795a6faffbb5e7b552e6feb00c654 Mon Sep 17 00:00:00 2001 From: Albert Astals Cid <albert.astals.cid@kdab.com> Date: Thu, 17 Jun 2021 16:32:28 +0200 -Subject: [PATCH 05/19] Remove unused QPointer<QQuickPointerMask> +Subject: [PATCH 01/21] Remove unused QPointer<QQuickPointerMask> Change-Id: I009fa6bbd8599dc3bb2e810176fe20e70ed50851 Reviewed-by: Shawn Rutledge <shawn.rutledge@qt.io> @@ -176,167 +31,12 @@ index fba383e268..0d63618622 100644 QPointF targetStartPos; QPointF lastPos; -- -2.36.0 - -From 8da88589929a1d82103c8bbfa80210f3c1af3714 Mon Sep 17 00:00:00 2001 -From: Dmitry Shachnev <mitya57@gmail.com> -Date: Wed, 18 Aug 2021 22:50:29 +0300 -Subject: [PATCH 06/19] Include <limits> in Yarr.h to fix build with GCC 11 -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -- <limits.h> (aka <climits>) is needed for UINT_MAX macro constant. -- <limits> is needed for std::numeric_limits. - -Without this fix, qtdeclarative failed to build on some platforms: - - In file included from jsruntime/qv4regexp_p.h:62, - from jsruntime/qv4regexp.cpp:40: - ../3rdparty/masm/yarr/Yarr.h:46:44: error: ‘numeric_limits’ is not a member of ‘std’ - 46 | static const unsigned offsetNoMatch = std::numeric_limits<unsigned>::max(); - | ^~~~~~~~~~~~~~ - -Pick-to: 5.15 6.2 -Change-Id: I7cc9f7bc6624a52c8659f09034ab16064da5fd2f -Reviewed-by: Albert Astals Cid <albert.astals.cid@kdab.com> -Reviewed-by: Ulf Hermann <ulf.hermann@qt.io> -(cherry picked from commit db58b8518e157b765bf2e01e6382a9eed4751f27) ---- - src/3rdparty/masm/yarr/Yarr.h | 1 + - 1 file changed, 1 insertion(+) - -diff --git a/src/3rdparty/masm/yarr/Yarr.h b/src/3rdparty/masm/yarr/Yarr.h -index ccf78f9880..2955ea7e72 100644 ---- a/src/3rdparty/masm/yarr/Yarr.h -+++ b/src/3rdparty/masm/yarr/Yarr.h -@@ -28,6 +28,7 @@ - #pragma once - - #include <limits.h> -+#include <limits> - #include "YarrErrorCode.h" - - namespace JSC { namespace Yarr { --- -2.36.0 +2.49.0 -From 103503f1cae9e928a4fa8b5e7e1f7af34f1add4d Mon Sep 17 00:00:00 2001 -From: Aleix Pol <aleixpol@kde.org> -Date: Tue, 21 Sep 2021 00:10:26 +0200 -Subject: [PATCH 07/19] QQuickLoader: Do not incubate if the source arrives - after setActive(false) - -Otherwise we end up in the crazy place of active being false but item -being non-null and forces us to workaround within the apps. - -Change-Id: I88c27c4b00ccec8b8e0c05a8e10b44fcabfc2e30 -Reviewed-by: Ulf Hermann <ulf.hermann@qt.io> -(cherry picked from commit e78c068700fa74ab3aca6a23ab2450563b1c3a5c) -Reviewed-by: Qt Cherry-pick Bot <cherrypick_bot@qt-project.org> ---- - src/quick/items/qquickloader.cpp | 3 +++ - .../data/loader-async-race-rect.qml | 10 ++++++++++ - .../qquickloader/data/loader-async-race.qml | 14 ++++++++++++++ - .../quick/qquickloader/tst_qquickloader.cpp | 19 +++++++++++++++++++ - 4 files changed, 46 insertions(+) - create mode 100644 tests/auto/quick/qquickloader/data/loader-async-race-rect.qml - create mode 100644 tests/auto/quick/qquickloader/data/loader-async-race.qml - -diff --git a/src/quick/items/qquickloader.cpp b/src/quick/items/qquickloader.cpp -index cb4f79a3c2..7fbe66fdda 100644 ---- a/src/quick/items/qquickloader.cpp -+++ b/src/quick/items/qquickloader.cpp -@@ -737,6 +737,9 @@ void QQuickLoaderPrivate::_q_sourceLoaded() - return; - } - -+ if (!active) -+ return; -+ - QQmlContext *creationContext = component->creationContext(); - if (!creationContext) creationContext = qmlContext(q); - itemContext = new QQmlContext(creationContext); -diff --git a/tests/auto/quick/qquickloader/data/loader-async-race-rect.qml b/tests/auto/quick/qquickloader/data/loader-async-race-rect.qml -new file mode 100644 -index 0000000000..a56dcea5ad ---- /dev/null -+++ b/tests/auto/quick/qquickloader/data/loader-async-race-rect.qml -@@ -0,0 +1,10 @@ -+import QtQuick 2.15 -+ -+Rectangle { -+ anchors.fill: parent -+ color: "blue" -+ Item { -+ Item { -+ } -+ } -+} -diff --git a/tests/auto/quick/qquickloader/data/loader-async-race.qml b/tests/auto/quick/qquickloader/data/loader-async-race.qml -new file mode 100644 -index 0000000000..8ba625c5c1 ---- /dev/null -+++ b/tests/auto/quick/qquickloader/data/loader-async-race.qml -@@ -0,0 +1,14 @@ -+import QtQuick 2.15 -+ -+Item { -+ id: root -+ Component.onCompleted: { -+ myloader.active = false -+ } -+ Loader { -+ id: myloader -+ anchors.fill: parent -+ asynchronous: true -+ source: "loader-async-race-rect.qml" -+ } -+} -diff --git a/tests/auto/quick/qquickloader/tst_qquickloader.cpp b/tests/auto/quick/qquickloader/tst_qquickloader.cpp -index 0f6c811adb..dddacbaa0b 100644 ---- a/tests/auto/quick/qquickloader/tst_qquickloader.cpp -+++ b/tests/auto/quick/qquickloader/tst_qquickloader.cpp -@@ -132,6 +132,7 @@ private slots: - void statusChangeOnlyEmittedOnce(); - - void setSourceAndCheckStatus(); -+ void asyncLoaderRace(); - }; - - Q_DECLARE_METATYPE(QList<QQmlError>) -@@ -1496,6 +1497,24 @@ void tst_QQuickLoader::setSourceAndCheckStatus() - QCOMPARE(loader->status(), QQuickLoader::Null); - } - -+void tst_QQuickLoader::asyncLoaderRace() -+{ -+ QQmlApplicationEngine engine; -+ auto url = testFileUrl("loader-async-race.qml"); -+ engine.load(url); -+ auto root = engine.rootObjects().at(0); -+ QVERIFY(root); -+ -+ QQuickLoader *loader = root->findChild<QQuickLoader *>(); -+ QCOMPARE(loader->active(), false); -+ QCOMPARE(loader->status(), QQuickLoader::Null); -+ QCOMPARE(loader->item(), nullptr); -+ -+ QSignalSpy spy(loader, &QQuickLoader::itemChanged); -+ QVERIFY(!spy.wait(100)); -+ QCOMPARE(loader->item(), nullptr); -+} -+ - QTEST_MAIN(tst_QQuickLoader) - - #include "tst_qquickloader.moc" --- -2.36.0 - -From 0fdd8a998075a8b52954724743d3a04c105c6ce2 Mon Sep 17 00:00:00 2001 +From cd192119255ac8a1b451aad04a82c58b294d5cbf Mon Sep 17 00:00:00 2001 From: Aleix Pol <aleixpol@kde.org> Date: Thu, 23 Sep 2021 03:43:04 +0200 -Subject: [PATCH 08/19] QQmlDelegateModel: Refresh the view when a column is +Subject: [PATCH 02/21] QQmlDelegateModel: Refresh the view when a column is added at 0 It can happen that a model reports n>0 rows but columns=0 (See @@ -357,7 +57,7 @@ Signed-off-by: Aleix Pol <aleixpol@kde.org> create mode 100644 tests/auto/qml/qqmldelegatemodel/data/redrawUponColumnChange.qml diff --git a/src/qmlmodels/qqmldelegatemodel.cpp b/src/qmlmodels/qqmldelegatemodel.cpp -index 26ded63c41..53e511303e 100644 +index 3b57edfc5d..5b7e767ae2 100644 --- a/src/qmlmodels/qqmldelegatemodel.cpp +++ b/src/qmlmodels/qqmldelegatemodel.cpp @@ -389,6 +389,12 @@ void QQmlDelegateModelPrivate::connectToAbstractItemModel() @@ -386,7 +86,7 @@ index 26ded63c41..53e511303e 100644 QObject::disconnect(aim, SIGNAL(dataChanged(QModelIndex,QModelIndex,QVector<int>)), q, SLOT(_q_dataChanged(QModelIndex,QModelIndex,QVector<int>))); QObject::disconnect(aim, SIGNAL(rowsMoved(QModelIndex,int,int,QModelIndex,int)), -@@ -1958,6 +1970,38 @@ void QQmlDelegateModel::_q_rowsMoved( +@@ -1979,6 +1991,38 @@ void QQmlDelegateModel::_q_rowsMoved( } } @@ -457,7 +157,7 @@ index 0000000000..206133bb39 + } +} diff --git a/tests/auto/qml/qqmldelegatemodel/tst_qqmldelegatemodel.cpp b/tests/auto/qml/qqmldelegatemodel/tst_qqmldelegatemodel.cpp -index 71550a50f3..4c1eae7ac7 100644 +index f0afdb16ca..e128d77c52 100644 --- a/tests/auto/qml/qqmldelegatemodel/tst_qqmldelegatemodel.cpp +++ b/tests/auto/qml/qqmldelegatemodel/tst_qqmldelegatemodel.cpp @@ -27,6 +27,8 @@ @@ -469,16 +169,16 @@ index 71550a50f3..4c1eae7ac7 100644 #include <QtQml/qqmlcomponent.h> #include <QtQmlModels/private/qqmldelegatemodel_p.h> #include <QtQuick/qquickview.h> -@@ -45,6 +47,7 @@ private slots: - void valueWithoutCallingObjectFirst_data(); - void valueWithoutCallingObjectFirst(); - void filterOnGroup_removeWhenCompleted(); +@@ -48,6 +50,7 @@ private slots: + void qtbug_86017(); + void contextAccessedByHandler(); + void deleteRace(); + void redrawUponColumnChange(); }; class AbstractItemModel : public QAbstractItemModel -@@ -149,6 +152,30 @@ void tst_QQmlDelegateModel::filterOnGroup_removeWhenCompleted() - QTest::qWaitFor([=]{ return model->count() == 2; } ); +@@ -187,6 +190,30 @@ void tst_QQmlDelegateModel::deleteRace() + QTRY_COMPARE(o->property("count").toInt(), 0); } +void tst_QQmlDelegateModel::redrawUponColumnChange() @@ -509,685 +209,12 @@ index 71550a50f3..4c1eae7ac7 100644 #include "tst_qqmldelegatemodel.moc" -- -2.36.0 - -From f2d1bfa96bedb09c27f52a802b03cbefb17a0257 Mon Sep 17 00:00:00 2001 -From: Vlad Zahorodnii <vlad.zahorodnii@kde.org> -Date: Sun, 10 Oct 2021 21:04:21 +0300 -Subject: [PATCH 09/19] Fix sweep step for tainted QObject JavaScript wrappers - -Currently, whenever the garbage collector runs, it will destroy all -valid tainted wrappers. - -Only null or undefined wrappers will be preserved in the -m_multiplyWrappedQObjects map. - -It seems like "!" was overlooked in -3b5d37ce3841c4bfdf1c629d33f0e33b881b47fb. Prior to that change, it -was "!it.value()->markBit()", so calling erase() in the then branch -did make sense. But with "!it.value().isNullOrUndefined()", erase() -will be called for every valid wrapper, which is the opposite what we -want. - -Pick-to: 5.15 6.2 -Change-Id: I2bf2630f538af8cbd4bfffcff29d67be6c278265 -Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io> -(cherry picked from commit e6b2f88d892dcf396580a61662f569bf69d6d9d1) ---- - src/qml/memory/qv4mm.cpp | 2 +- - tests/auto/qml/qjsengine/tst_qjsengine.cpp | 39 ++++++++++++++++++++++ - tests/auto/qml/qv4mm/tst_qv4mm.cpp | 6 ++-- - 3 files changed, 43 insertions(+), 4 deletions(-) - -diff --git a/src/qml/memory/qv4mm.cpp b/src/qml/memory/qv4mm.cpp -index 06caf04e5a..da149a67c4 100644 ---- a/src/qml/memory/qv4mm.cpp -+++ b/src/qml/memory/qv4mm.cpp -@@ -981,7 +981,7 @@ void MemoryManager::sweep(bool lastSweep, ClassDestroyStatsCallback classCountPt - - if (MultiplyWrappedQObjectMap *multiplyWrappedQObjects = engine->m_multiplyWrappedQObjects) { - for (MultiplyWrappedQObjectMap::Iterator it = multiplyWrappedQObjects->begin(); it != multiplyWrappedQObjects->end();) { -- if (!it.value().isNullOrUndefined()) -+ if (it.value().isNullOrUndefined()) - it = multiplyWrappedQObjects->erase(it); - else - ++it; -diff --git a/tests/auto/qml/qjsengine/tst_qjsengine.cpp b/tests/auto/qml/qjsengine/tst_qjsengine.cpp -index 3b7d74df63..b75bf820d5 100644 ---- a/tests/auto/qml/qjsengine/tst_qjsengine.cpp -+++ b/tests/auto/qml/qjsengine/tst_qjsengine.cpp -@@ -102,6 +102,7 @@ private slots: - void valueConversion_RegularExpression(); - void castWithMultipleInheritance(); - void collectGarbage(); -+ void collectGarbageNestedWrappersTwoEngines(); - void gcWithNestedDataStructure(); - void stacktrace(); - void numberParsing_data(); -@@ -1809,6 +1810,44 @@ void tst_QJSEngine::collectGarbage() - QVERIFY(ptr.isNull()); - } - -+class TestObjectContainer : public QObject -+{ -+ Q_OBJECT -+ Q_PROPERTY(QObject *dummy MEMBER m_dummy CONSTANT) -+ -+public: -+ TestObjectContainer() : m_dummy(new QObject(this)) {} -+ -+private: -+ QObject *m_dummy; -+}; -+ -+void tst_QJSEngine::collectGarbageNestedWrappersTwoEngines() -+{ -+ QJSEngine engine1; -+ QJSEngine engine2; -+ -+ TestObjectContainer container; -+ QQmlEngine::setObjectOwnership(&container, QQmlEngine::CppOwnership); -+ -+ engine1.globalObject().setProperty("foobar", engine1.newQObject(&container)); -+ engine2.globalObject().setProperty("foobar", engine2.newQObject(&container)); -+ -+ engine1.evaluate("foobar.dummy.baz = 42"); -+ engine2.evaluate("foobar.dummy.baz = 43"); -+ -+ QCOMPARE(engine1.evaluate("foobar.dummy.baz").toInt(), 42); -+ QCOMPARE(engine2.evaluate("foobar.dummy.baz").toInt(), 43); -+ -+ engine1.collectGarbage(); -+ engine2.collectGarbage(); -+ -+ // The GC should not collect dummy object wrappers neither in engine1 nor engine2, we -+ // verify that by checking whether the baz property still has its previous value. -+ QCOMPARE(engine1.evaluate("foobar.dummy.baz").toInt(), 42); -+ QCOMPARE(engine2.evaluate("foobar.dummy.baz").toInt(), 43); -+} -+ - void tst_QJSEngine::gcWithNestedDataStructure() - { - // The GC must be able to traverse deeply nested objects, otherwise this -diff --git a/tests/auto/qml/qv4mm/tst_qv4mm.cpp b/tests/auto/qml/qv4mm/tst_qv4mm.cpp -index 5d635aa63b..824fd89e5b 100644 ---- a/tests/auto/qml/qv4mm/tst_qv4mm.cpp -+++ b/tests/auto/qml/qv4mm/tst_qv4mm.cpp -@@ -76,10 +76,10 @@ void tst_qv4mm::multiWrappedQObjects() - QCOMPARE(engine1.memoryManager->m_pendingFreedObjectWrapperValue.size(), 1); - QCOMPARE(engine2.memoryManager->m_pendingFreedObjectWrapperValue.size(), 0); - -- // Moves the additional WeakValue from m_multiplyWrappedQObjects to -- // m_pendingFreedObjectWrapperValue. It's still alive after all. -+ // The additional WeakValue from m_multiplyWrappedQObjects hasn't been moved -+ // to m_pendingFreedObjectWrapperValue yet. It's still alive after all. - engine1.memoryManager->runGC(); -- QCOMPARE(engine1.memoryManager->m_pendingFreedObjectWrapperValue.size(), 2); -+ QCOMPARE(engine1.memoryManager->m_pendingFreedObjectWrapperValue.size(), 1); - - // engine2 doesn't own the object as engine1 was the first to wrap it above. - // Therefore, no effect here. --- -2.36.0 - -From b884339e8b6dd8dcaed9704afda2ebed4fcaf9b5 Mon Sep 17 00:00:00 2001 -From: Eskil Abrahamsen Blomfeldt <eskil.abrahamsen-blomfeldt@qt.io> -Date: Tue, 12 Oct 2021 13:13:01 +0200 -Subject: [PATCH 10/19] Fix distorted text with subpixel matrix translation - -We would pixel-align native text *before* applying the -model-view matrix, which would cause GL_NEAREST artifacts to -show up when the text was positioned at a subpixel offset in -some cases. Instead, we pixel-align the coordinates after mapping -them to the view frustum, but before applying the projection to the -screen. - -To make it easier to modify the buffer layout for the shaders the -next time, this also adds some constants for offsets. - -[ChangeLog][Text] Fixed an issue where text using NativeRendering -would look slightly skewed if it was inside a parent that had -been positioned at a subpixel offset. - -Pick-to: 5.15 6.2 -Fixes: QTBUG-96112 -Fixes: QTBUG-83626 -Task-number: QTBUG-55638 -Change-Id: Ifb785ad5830093df94afc75a7bc288e24ca7aa38 -Reviewed-by: Eirik Aavitsland <eirik.aavitsland@qt.io> -(cherry picked from commit b21948f5e811ce1b7abf065bc48af61a231e86f4) ---- - .../scenegraph/qsgdefaultglyphnode_p.cpp | 46 ++++++---- - .../scenegraph/shaders_ng/24bittextmask.frag | 5 +- - .../scenegraph/shaders_ng/32bitcolortext.frag | 5 +- - .../scenegraph/shaders_ng/8bittextmask.frag | 3 +- - .../scenegraph/shaders_ng/8bittextmask_a.frag | 3 +- - .../scenegraph/shaders_ng/outlinedtext.frag | 5 +- - .../scenegraph/shaders_ng/outlinedtext.vert | 9 +- - .../scenegraph/shaders_ng/outlinedtext_a.frag | 5 +- - .../scenegraph/shaders_ng/styledtext.frag | 3 +- - .../scenegraph/shaders_ng/styledtext.vert | 7 +- - .../scenegraph/shaders_ng/styledtext_a.frag | 3 +- - src/quick/scenegraph/shaders_ng/textmask.frag | 3 +- - src/quick/scenegraph/shaders_ng/textmask.vert | 7 +- - ...text_nativerendering_subpixelpositions.qml | 91 +++++++++++++++++++ - 14 files changed, 155 insertions(+), 40 deletions(-) - create mode 100644 tests/manual/scenegraph_lancelot/data/text/text_nativerendering_subpixelpositions.qml - -diff --git a/src/quick/scenegraph/qsgdefaultglyphnode_p.cpp b/src/quick/scenegraph/qsgdefaultglyphnode_p.cpp -index 3c60f830de..0fd6581dc4 100644 ---- a/src/quick/scenegraph/qsgdefaultglyphnode_p.cpp -+++ b/src/quick/scenegraph/qsgdefaultglyphnode_p.cpp -@@ -428,6 +428,18 @@ QSGTextMaskRhiShader::QSGTextMaskRhiShader(QFontEngine::GlyphFormat glyphFormat) - QStringLiteral(":/qt-project.org/scenegraph/shaders_ng/textmask.frag.qsb")); - } - -+enum UbufOffset { -+ ModelViewMatrixOffset = 0, -+ ProjectionMatrixOffset = ModelViewMatrixOffset + 64, -+ ColorOffset = ProjectionMatrixOffset + 64, -+ TextureScaleOffset = ColorOffset + 16, -+ DprOffset = TextureScaleOffset + 8, -+ -+ // + 1 float padding (vec4 must be aligned to 16) -+ StyleColorOffset = DprOffset + 4 + 4, -+ ShiftOffset = StyleColorOffset + 16 -+}; -+ - bool QSGTextMaskRhiShader::updateUniformData(RenderState &state, - QSGMaterial *newMaterial, QSGMaterial *oldMaterial) - { -@@ -443,11 +455,14 @@ bool QSGTextMaskRhiShader::updateUniformData(RenderState &state, - - bool changed = false; - QByteArray *buf = state.uniformData(); -- Q_ASSERT(buf->size() >= 92); -+ Q_ASSERT(buf->size() >= DprOffset + 4); - - if (state.isMatrixDirty()) { -- const QMatrix4x4 m = state.combinedMatrix(); -- memcpy(buf->data(), m.constData(), 64); -+ const QMatrix4x4 mv = state.modelViewMatrix(); -+ memcpy(buf->data() + ModelViewMatrixOffset, mv.constData(), 64); -+ const QMatrix4x4 p = state.projectionMatrix(); -+ memcpy(buf->data() + ProjectionMatrixOffset, p.constData(), 64); -+ - changed = true; - } - -@@ -456,13 +471,13 @@ bool QSGTextMaskRhiShader::updateUniformData(RenderState &state, - if (updated || !oldMat || oldRtex != newRtex) { - const QVector2D textureScale = QVector2D(1.0f / mat->rhiGlyphCache()->width(), - 1.0f / mat->rhiGlyphCache()->height()); -- memcpy(buf->data() + 64 + 16, &textureScale, 8); -+ memcpy(buf->data() + TextureScaleOffset, &textureScale, 8); - changed = true; - } - - if (!oldMat) { - float dpr = state.devicePixelRatio(); -- memcpy(buf->data() + 64 + 16 + 8, &dpr, 4); -+ memcpy(buf->data() + DprOffset, &dpr, 4); - } - - // move texture uploads/copies onto the renderer's soon-to-be-committed list -@@ -510,11 +525,11 @@ bool QSG8BitTextMaskRhiShader::updateUniformData(RenderState &state, - QSGTextMaskMaterial *oldMat = static_cast<QSGTextMaskMaterial *>(oldMaterial); - - QByteArray *buf = state.uniformData(); -- Q_ASSERT(buf->size() >= 80); -+ Q_ASSERT(buf->size() >= ColorOffset + 16); - - if (oldMat == nullptr || mat->color() != oldMat->color() || state.isOpacityDirty()) { - const QVector4D color = qsg_premultiply(mat->color(), state.opacity()); -- memcpy(buf->data() + 64, &color, 16); -+ memcpy(buf->data() + ColorOffset, &color, 16); - changed = true; - } - -@@ -553,12 +568,12 @@ bool QSG24BitTextMaskRhiShader::updateUniformData(RenderState &state, - QSGTextMaskMaterial *oldMat = static_cast<QSGTextMaskMaterial *>(oldMaterial); - - QByteArray *buf = state.uniformData(); -- Q_ASSERT(buf->size() >= 92); -+ Q_ASSERT(buf->size() >= ColorOffset + 16); - - if (oldMat == nullptr || mat->color() != oldMat->color() || state.isOpacityDirty()) { - // shader takes vec4 but uses alpha only; coloring happens via the blend constant - const QVector4D color = qsg_premultiply(mat->color(), state.opacity()); -- memcpy(buf->data() + 64, &color, 16); -+ memcpy(buf->data() + ColorOffset, &color, 16); - changed = true; - } - -@@ -608,12 +623,12 @@ bool QSG32BitColorTextRhiShader::updateUniformData(RenderState &state, - QSGTextMaskMaterial *oldMat = static_cast<QSGTextMaskMaterial *>(oldMaterial); - - QByteArray *buf = state.uniformData(); -- Q_ASSERT(buf->size() >= 92); -+ Q_ASSERT(buf->size() >= ColorOffset + 16); - - if (oldMat == nullptr || mat->color() != oldMat->color() || state.isOpacityDirty()) { - // shader takes vec4 but uses alpha only - const QVector4D color(0, 0, 0, mat->color().w() * state.opacity()); -- memcpy(buf->data() + 64, &color, 16); -+ memcpy(buf->data() + ColorOffset, &color, 16); - changed = true; - } - -@@ -649,20 +664,17 @@ bool QSGStyledTextRhiShader::updateUniformData(RenderState &state, - QSGStyledTextMaterial *oldMat = static_cast<QSGStyledTextMaterial *>(oldMaterial); - - QByteArray *buf = state.uniformData(); -- Q_ASSERT(buf->size() >= 120); -- -- // matrix..dpr + 1 float padding (vec4 must be aligned to 16) -- const int startOffset = 64 + 16 + 8 + 4 + 4; -+ Q_ASSERT(buf->size() >= ShiftOffset + 8); - - if (oldMat == nullptr || mat->styleColor() != oldMat->styleColor() || state.isOpacityDirty()) { - const QVector4D styleColor = qsg_premultiply(mat->styleColor(), state.opacity()); -- memcpy(buf->data() + startOffset, &styleColor, 16); -+ memcpy(buf->data() + StyleColorOffset, &styleColor, 16); - changed = true; - } - - if (oldMat == nullptr || oldMat->styleShift() != mat->styleShift()) { - const QVector2D v = mat->styleShift(); -- memcpy(buf->data() + startOffset + 16, &v, 8); -+ memcpy(buf->data() + ShiftOffset, &v, 8); - changed = true; - } - -diff --git a/src/quick/scenegraph/shaders_ng/24bittextmask.frag b/src/quick/scenegraph/shaders_ng/24bittextmask.frag -index bc3826a924..ed8da4cd30 100644 ---- a/src/quick/scenegraph/shaders_ng/24bittextmask.frag -+++ b/src/quick/scenegraph/shaders_ng/24bittextmask.frag -@@ -6,8 +6,9 @@ layout(location = 0) out vec4 fragColor; - layout(binding = 1) uniform sampler2D _qt_texture; - - layout(std140, binding = 0) uniform buf { -- mat4 matrix; -- vec4 color; // only alpha is used, but must be vec4 due to layout compat -+ mat4 modelViewMatrix; -+ mat4 projectionMatrix; -+ vec4 color; - vec2 textureScale; - float dpr; - } ubuf; -diff --git a/src/quick/scenegraph/shaders_ng/32bitcolortext.frag b/src/quick/scenegraph/shaders_ng/32bitcolortext.frag -index 63e445f90b..4198a4d339 100644 ---- a/src/quick/scenegraph/shaders_ng/32bitcolortext.frag -+++ b/src/quick/scenegraph/shaders_ng/32bitcolortext.frag -@@ -6,8 +6,9 @@ layout(location = 0) out vec4 fragColor; - layout(binding = 1) uniform sampler2D _qt_texture; - - layout(std140, binding = 0) uniform buf { -- mat4 matrix; -- vec4 color; // only alpha is used, but must be vec4 due to layout compat -+ mat4 modelViewMatrix; -+ mat4 projectionMatrix; -+ vec4 color; - vec2 textureScale; - float dpr; - } ubuf; -diff --git a/src/quick/scenegraph/shaders_ng/8bittextmask.frag b/src/quick/scenegraph/shaders_ng/8bittextmask.frag -index 6304e821ff..a06743876d 100644 ---- a/src/quick/scenegraph/shaders_ng/8bittextmask.frag -+++ b/src/quick/scenegraph/shaders_ng/8bittextmask.frag -@@ -6,7 +6,8 @@ layout(location = 0) out vec4 fragColor; - layout(binding = 1) uniform sampler2D _qt_texture; - - layout(std140, binding = 0) uniform buf { -- mat4 matrix; -+ mat4 modelViewMatrix; -+ mat4 projectionMatrix; - vec4 color; - vec2 textureScale; - float dpr; -diff --git a/src/quick/scenegraph/shaders_ng/8bittextmask_a.frag b/src/quick/scenegraph/shaders_ng/8bittextmask_a.frag -index 0d0fa1cd3a..f725cbc5e7 100644 ---- a/src/quick/scenegraph/shaders_ng/8bittextmask_a.frag -+++ b/src/quick/scenegraph/shaders_ng/8bittextmask_a.frag -@@ -6,7 +6,8 @@ layout(location = 0) out vec4 fragColor; - layout(binding = 1) uniform sampler2D _qt_texture; - - layout(std140, binding = 0) uniform buf { -- mat4 matrix; -+ mat4 modelViewMatrix; -+ mat4 projectionMatrix; - vec4 color; - vec2 textureScale; - float dpr; -diff --git a/src/quick/scenegraph/shaders_ng/outlinedtext.frag b/src/quick/scenegraph/shaders_ng/outlinedtext.frag -index 947d161a50..e2f82d3845 100644 ---- a/src/quick/scenegraph/shaders_ng/outlinedtext.frag -+++ b/src/quick/scenegraph/shaders_ng/outlinedtext.frag -@@ -11,11 +11,12 @@ layout(location = 0) out vec4 fragColor; - layout(binding = 1) uniform sampler2D _qt_texture; - - layout(std140, binding = 0) uniform buf { -- // must match styledtext -- mat4 matrix; -+ mat4 modelViewMatrix; -+ mat4 projectionMatrix; - vec4 color; - vec2 textureScale; - float dpr; -+ // the above must stay compatible with textmask/8bittextmask - vec4 styleColor; - vec2 shift; - } ubuf; -diff --git a/src/quick/scenegraph/shaders_ng/outlinedtext.vert b/src/quick/scenegraph/shaders_ng/outlinedtext.vert -index 023f9dfdc2..4068e42f28 100644 ---- a/src/quick/scenegraph/shaders_ng/outlinedtext.vert -+++ b/src/quick/scenegraph/shaders_ng/outlinedtext.vert -@@ -10,11 +10,12 @@ layout(location = 3) out vec2 sCoordLeft; - layout(location = 4) out vec2 sCoordRight; - - layout(std140, binding = 0) uniform buf { -- // must match styledtext -- mat4 matrix; -+ mat4 modelViewMatrix; -+ mat4 projectionMatrix; - vec4 color; - vec2 textureScale; - float dpr; -+ // the above must stay compatible with textmask/8bittextmask - vec4 styleColor; - vec2 shift; - } ubuf; -@@ -28,6 +29,6 @@ void main() - sCoordDown = (tCoord - vec2(0.0, 1.0)) * ubuf.textureScale; - sCoordLeft = (tCoord - vec2(-1.0, 0.0)) * ubuf.textureScale; - sCoordRight = (tCoord - vec2(1.0, 0.0)) * ubuf.textureScale; -- vec3 dprSnapPos = floor(vCoord.xyz * ubuf.dpr + 0.5) / ubuf.dpr; -- gl_Position = ubuf.matrix * vec4(dprSnapPos, vCoord.w); -+ vec4 xformed = ubuf.modelViewMatrix * vCoord; -+ gl_Position = ubuf.projectionMatrix * vec4(floor(xformed.xyz * ubuf.dpr + 0.5) / ubuf.dpr, xformed.w); - } -diff --git a/src/quick/scenegraph/shaders_ng/outlinedtext_a.frag b/src/quick/scenegraph/shaders_ng/outlinedtext_a.frag -index 5b7bd9ca82..274d891a3c 100644 ---- a/src/quick/scenegraph/shaders_ng/outlinedtext_a.frag -+++ b/src/quick/scenegraph/shaders_ng/outlinedtext_a.frag -@@ -11,11 +11,12 @@ layout(location = 0) out vec4 fragColor; - layout(binding = 1) uniform sampler2D _qt_texture; - - layout(std140, binding = 0) uniform buf { -- // must match styledtext -- mat4 matrix; -+ mat4 modelViewMatrix; -+ mat4 projectionMatrix; - vec4 color; - vec2 textureScale; - float dpr; -+ // the above must stay compatible with textmask/8bittextmask - vec4 styleColor; - vec2 shift; - } ubuf; -diff --git a/src/quick/scenegraph/shaders_ng/styledtext.frag b/src/quick/scenegraph/shaders_ng/styledtext.frag -index 0b16396037..2e380dfeae 100644 ---- a/src/quick/scenegraph/shaders_ng/styledtext.frag -+++ b/src/quick/scenegraph/shaders_ng/styledtext.frag -@@ -8,7 +8,8 @@ layout(location = 0) out vec4 fragColor; - layout(binding = 1) uniform sampler2D _qt_texture; - - layout(std140, binding = 0) uniform buf { -- mat4 matrix; -+ mat4 modelViewMatrix; -+ mat4 projectionMatrix; - vec4 color; - vec2 textureScale; - float dpr; -diff --git a/src/quick/scenegraph/shaders_ng/styledtext.vert b/src/quick/scenegraph/shaders_ng/styledtext.vert -index beadf07c79..271dae8d8a 100644 ---- a/src/quick/scenegraph/shaders_ng/styledtext.vert -+++ b/src/quick/scenegraph/shaders_ng/styledtext.vert -@@ -7,7 +7,8 @@ layout(location = 0) out vec2 sampleCoord; - layout(location = 1) out vec2 shiftedSampleCoord; - - layout(std140, binding = 0) uniform buf { -- mat4 matrix; -+ mat4 modelViewMatrix; -+ mat4 projectionMatrix; - vec4 color; - vec2 textureScale; - float dpr; -@@ -22,6 +23,6 @@ void main() - { - sampleCoord = tCoord * ubuf.textureScale; - shiftedSampleCoord = (tCoord - ubuf.shift) * ubuf.textureScale; -- vec3 dprSnapPos = floor(vCoord.xyz * ubuf.dpr + 0.5) / ubuf.dpr; -- gl_Position = ubuf.matrix * vec4(dprSnapPos, vCoord.w); -+ vec4 xformed = ubuf.modelViewMatrix * vCoord; -+ gl_Position = ubuf.projectionMatrix * vec4(floor(xformed.xyz * ubuf.dpr + 0.5) / ubuf.dpr, xformed.w); - } -diff --git a/src/quick/scenegraph/shaders_ng/styledtext_a.frag b/src/quick/scenegraph/shaders_ng/styledtext_a.frag -index b673137895..62e162c851 100644 ---- a/src/quick/scenegraph/shaders_ng/styledtext_a.frag -+++ b/src/quick/scenegraph/shaders_ng/styledtext_a.frag -@@ -8,7 +8,8 @@ layout(location = 0) out vec4 fragColor; - layout(binding = 1) uniform sampler2D _qt_texture; - - layout(std140, binding = 0) uniform buf { -- mat4 matrix; -+ mat4 modelViewMatrix; -+ mat4 projectionMatrix; - vec4 color; - vec2 textureScale; - float dpr; -diff --git a/src/quick/scenegraph/shaders_ng/textmask.frag b/src/quick/scenegraph/shaders_ng/textmask.frag -index 518d5c965f..ed8da4cd30 100644 ---- a/src/quick/scenegraph/shaders_ng/textmask.frag -+++ b/src/quick/scenegraph/shaders_ng/textmask.frag -@@ -6,7 +6,8 @@ layout(location = 0) out vec4 fragColor; - layout(binding = 1) uniform sampler2D _qt_texture; - - layout(std140, binding = 0) uniform buf { -- mat4 matrix; -+ mat4 modelViewMatrix; -+ mat4 projectionMatrix; - vec4 color; - vec2 textureScale; - float dpr; -diff --git a/src/quick/scenegraph/shaders_ng/textmask.vert b/src/quick/scenegraph/shaders_ng/textmask.vert -index 9d80d5dadb..e0b3c01bce 100644 ---- a/src/quick/scenegraph/shaders_ng/textmask.vert -+++ b/src/quick/scenegraph/shaders_ng/textmask.vert -@@ -6,7 +6,8 @@ layout(location = 1) in vec2 tCoord; - layout(location = 0) out vec2 sampleCoord; - - layout(std140, binding = 0) uniform buf { -- mat4 matrix; -+ mat4 modelViewMatrix; -+ mat4 projectionMatrix; - vec4 color; - vec2 textureScale; - float dpr; -@@ -17,6 +18,6 @@ out gl_PerVertex { vec4 gl_Position; }; - void main() - { - sampleCoord = tCoord * ubuf.textureScale; -- vec3 dprSnapPos = floor(vCoord.xyz * ubuf.dpr + 0.5) / ubuf.dpr; -- gl_Position = ubuf.matrix * vec4(dprSnapPos, vCoord.w); -+ vec4 xformed = ubuf.modelViewMatrix * vCoord; -+ gl_Position = ubuf.projectionMatrix * vec4(floor(xformed.xyz * ubuf.dpr + 0.5) / ubuf.dpr, xformed.w); - } -diff --git a/tests/manual/scenegraph_lancelot/data/text/text_nativerendering_subpixelpositions.qml b/tests/manual/scenegraph_lancelot/data/text/text_nativerendering_subpixelpositions.qml -new file mode 100644 -index 0000000000..c60fc4d8b0 ---- /dev/null -+++ b/tests/manual/scenegraph_lancelot/data/text/text_nativerendering_subpixelpositions.qml -@@ -0,0 +1,91 @@ -+import QtQuick 2.0 -+ -+//vary font style, native rendering at non-integer offsets -+ -+Item { -+ id: topLevel -+ width: 320 -+ height: 580 -+ -+ Repeater { -+ model: [Text.Normal, Text.Outline, Text.Raised, Text.Sunken] -+ Text { -+ y: 20 * index -+ clip: true -+ renderType: Text.NativeRendering -+ width: parent.width -+ wrapMode: Text.Wrap -+ font.pointSize: 10 -+ style: modelData -+ styleColor: "green" -+ text: "The quick fox jumps in style " + modelData -+ } -+ } -+ -+ Repeater { -+ model: [Text.Normal, Text.Outline, Text.Raised, Text.Sunken] -+ Text { -+ y: 100.5 + 20 * index -+ clip: true -+ renderType: Text.NativeRendering -+ width: parent.width -+ wrapMode: Text.Wrap -+ font.pointSize: 10 -+ style: modelData -+ styleColor: "green" -+ text: "The quick fox jumps in style " + modelData -+ } -+ } -+ -+ Repeater { -+ model: [Text.Normal, Text.Outline, Text.Raised, Text.Sunken] -+ Text { -+ y: 200.5 + 20 * index -+ x: 0.5 -+ clip: true -+ renderType: Text.NativeRendering -+ width: parent.width -+ wrapMode: Text.Wrap -+ font.pointSize: 10 -+ style: modelData -+ styleColor: "green" -+ text: "The quick fox jumps in style " + modelData -+ } -+ } -+ -+ Repeater { -+ model: [Text.Normal, Text.Outline, Text.Raised, Text.Sunken] -+ Text { -+ y: 300.5 + 20 * index -+ x: 0.5 -+ clip: true -+ renderType: Text.NativeRendering -+ width: parent.width -+ wrapMode: Text.Wrap -+ font.pointSize: 10 -+ style: modelData -+ styleColor: "green" -+ text: "The quick fox jumps in style " + modelData -+ } -+ } -+ -+ Repeater { -+ model: [Text.Normal, Text.Outline, Text.Raised, Text.Sunken] -+ Rectangle { -+ y: 400.5 + 20 * index -+ x: 0.5 -+ width: topLevel.width -+ height: topLevel.height -+ clip: true -+ Text { -+ renderType: Text.NativeRendering -+ width: parent.width -+ wrapMode: Text.Wrap -+ font.pointSize: 10 -+ style: modelData -+ styleColor: "green" -+ text: "The quick fox jumps in style " + modelData -+ } -+ } -+ } -+} --- -2.36.0 - -From 8b0a4b1a329010e056b19fdd9940bad2036b5f57 Mon Sep 17 00:00:00 2001 -From: Laszlo Agocs <laszlo.agocs@qt.io> -Date: Mon, 11 Oct 2021 15:37:33 +0200 -Subject: [PATCH 11/19] Revert "Fix for possible crash in - QSGDefaultLayer::grab" -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -This reverts commit 1c5de027d0c31d1d6697bd0557128d92207763d8. - -The fix here is not correct. Calling a QSGRhiLayer function from the gui -thread is very wrong and can cause a set of unexpected issues. The -Address Sanitizer catches this by recognizing that the render thread is -trying to do something with an object destroyed in the meantime on the -main thread in the layer->setItem(null) call. - -The issue the original fix is trying to address needs to be addressed in -some different form. - -Fixes: QTBUG-94975 -Pick-to: 6.2 6.1 5.15 -Change-Id: I46f904026281201fc6d233ed7d3bdc7080934afe -Reviewed-by: Christian Strømme <christian.stromme@qt.io> -(cherry picked from commit a5f0361622eb08eab6c3474d5fc249d1962e3d1e) ---- - src/quick/items/qquickshadereffectsource.cpp | 8 -------- - src/quick/items/qquickshadereffectsource_p.h | 1 - - 2 files changed, 9 deletions(-) - -diff --git a/src/quick/items/qquickshadereffectsource.cpp b/src/quick/items/qquickshadereffectsource.cpp -index 4f61d61309..b298ed74da 100644 ---- a/src/quick/items/qquickshadereffectsource.cpp -+++ b/src/quick/items/qquickshadereffectsource.cpp -@@ -344,7 +344,6 @@ void QQuickShaderEffectSource::setSourceItem(QQuickItem *item) - d->refFromEffectItem(m_hideSource); - d->addItemChangeListener(this, QQuickItemPrivate::Geometry); - connect(m_sourceItem, SIGNAL(destroyed(QObject*)), this, SLOT(sourceItemDestroyed(QObject*))); -- connect(m_sourceItem, SIGNAL(parentChanged(QQuickItem*)), this, SLOT(sourceItemParentChanged(QQuickItem*))); - } else { - qWarning("ShaderEffectSource: sourceItem and ShaderEffectSource must both be children of the same window."); - m_sourceItem = nullptr; -@@ -364,13 +363,6 @@ void QQuickShaderEffectSource::sourceItemDestroyed(QObject *item) - } - - --void QQuickShaderEffectSource::sourceItemParentChanged(QQuickItem *parent) --{ -- if (!parent && m_texture) -- m_texture->setItem(0); --} -- -- - /*! - \qmlproperty rect QtQuick::ShaderEffectSource::sourceRect - -diff --git a/src/quick/items/qquickshadereffectsource_p.h b/src/quick/items/qquickshadereffectsource_p.h -index 4deb6c70a3..c0a1ccab78 100644 ---- a/src/quick/items/qquickshadereffectsource_p.h -+++ b/src/quick/items/qquickshadereffectsource_p.h -@@ -173,7 +173,6 @@ Q_SIGNALS: - private Q_SLOTS: - void sourceItemDestroyed(QObject *item); - void invalidateSceneGraph(); -- void sourceItemParentChanged(QQuickItem *parent); - - protected: - void releaseResources() override; --- -2.36.0 +2.49.0 -From 0e201d3561cecc8a1e982f81095f14af1dc3ceca Mon Sep 17 00:00:00 2001 +From 608d9a277e1d3e6a84b711e6828a8f50ce26d7ef Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Arve=20S=C3=A6ther?= <jan-arve.saether@qt.io> Date: Thu, 3 Sep 2020 10:51:01 +0200 -Subject: [PATCH 12/19] Fix TapHandler so that it actually registers a tap +Subject: [PATCH 03/21] Fix TapHandler so that it actually registers a tap This bug caused all quick examples that used the shared\LauncherList.qml to be broken. @@ -1211,7 +238,7 @@ Reviewed-by: Shawn Rutledge <shawn.rutledge@qt.io> 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/quick/handlers/qquickhandlerpoint.cpp b/src/quick/handlers/qquickhandlerpoint.cpp -index 72efdfd0f4..6aef3545dd 100644 +index 7103206470..02141b9a9e 100644 --- a/src/quick/handlers/qquickhandlerpoint.cpp +++ b/src/quick/handlers/qquickhandlerpoint.cpp @@ -82,7 +82,7 @@ void QQuickHandlerPoint::localize(QQuickItem *item) @@ -1233,7 +260,7 @@ index 72efdfd0f4..6aef3545dd 100644 // all points are required to be from the same event, so pressed buttons and modifiers should be the same m_pressedButtons = points.first().pressedButtons(); diff --git a/src/quick/handlers/qquicksinglepointhandler.cpp b/src/quick/handlers/qquicksinglepointhandler.cpp -index b51f53b74f..89081b4e84 100644 +index d785d8c0ca..a508de455d 100644 --- a/src/quick/handlers/qquicksinglepointhandler.cpp +++ b/src/quick/handlers/qquicksinglepointhandler.cpp @@ -75,7 +75,7 @@ bool QQuickSinglePointHandler::wantsPointerEvent(QQuickPointerEvent *event) @@ -1255,12 +282,12 @@ index b51f53b74f..89081b4e84 100644 void QQuickSinglePointHandler::handlePointerEventImpl(QQuickPointerEvent *event) -- -2.36.0 +2.49.0 -From 5af400361da5d66427c68bf743c8def70b7cbc8e Mon Sep 17 00:00:00 2001 +From f5dd04cc3e358f7e8430b60e78ba90b6386b1cba Mon Sep 17 00:00:00 2001 From: Albert Astals Cid <aacid@kde.org> Date: Tue, 16 Nov 2021 22:43:37 +0100 -Subject: [PATCH 13/19] Revert "Fix TapHandler so that it actually registers a +Subject: [PATCH 04/21] Revert "Fix TapHandler so that it actually registers a tap" This reverts commit 36e8ccd434f948e4f11a8f9d59139ec072e41ff5. @@ -1272,7 +299,7 @@ It's causing regresions 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/quick/handlers/qquickhandlerpoint.cpp b/src/quick/handlers/qquickhandlerpoint.cpp -index 6aef3545dd..72efdfd0f4 100644 +index 02141b9a9e..7103206470 100644 --- a/src/quick/handlers/qquickhandlerpoint.cpp +++ b/src/quick/handlers/qquickhandlerpoint.cpp @@ -82,7 +82,7 @@ void QQuickHandlerPoint::localize(QQuickItem *item) @@ -1294,7 +321,7 @@ index 6aef3545dd..72efdfd0f4 100644 // all points are required to be from the same event, so pressed buttons and modifiers should be the same m_pressedButtons = points.first().pressedButtons(); diff --git a/src/quick/handlers/qquicksinglepointhandler.cpp b/src/quick/handlers/qquicksinglepointhandler.cpp -index 89081b4e84..b51f53b74f 100644 +index a508de455d..d785d8c0ca 100644 --- a/src/quick/handlers/qquicksinglepointhandler.cpp +++ b/src/quick/handlers/qquicksinglepointhandler.cpp @@ -75,7 +75,7 @@ bool QQuickSinglePointHandler::wantsPointerEvent(QQuickPointerEvent *event) @@ -1316,99 +343,12 @@ index 89081b4e84..b51f53b74f 100644 void QQuickSinglePointHandler::handlePointerEventImpl(QQuickPointerEvent *event) -- -2.36.0 - -From 9a3aaa96c58d167ab9eec0d0c8105853e8c6117a Mon Sep 17 00:00:00 2001 -From: Marc Mutz <marc.mutz@qt.io> -Date: Tue, 21 Dec 2021 09:20:17 +0100 -Subject: [PATCH 14/19] QQmlJs::FixedPoolArray: fix UB (precondition violation) - in allocate() - -Says ubsan: - - qqmljsfixedpoolarray_p.h:90:19: runtime error: null pointer passed as argument 2, which is declared to never be null - -Fix, like in so many other places, by a size check. - -Pick-to: 6.3 6.2 5.15 -Change-Id: I9181d6ecb467c2dc726978ce7f93b35a6bf2f944 -Reviewed-by: Lars Knoll <lars.knoll@qt.io> -(cherry picked from commit d74e931f3fc2587ac6d1e2930acbbe54ea5be2b5) ---- - src/qml/common/qqmljsfixedpoolarray_p.h | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/src/qml/common/qqmljsfixedpoolarray_p.h b/src/qml/common/qqmljsfixedpoolarray_p.h -index b65b994d6c..15a8cd6878 100644 ---- a/src/qml/common/qqmljsfixedpoolarray_p.h -+++ b/src/qml/common/qqmljsfixedpoolarray_p.h -@@ -86,7 +86,7 @@ public: - if (QTypeInfo<T>::isComplex) { - for (int i = 0; i < count; ++i) - new (data + i) T(vector.at(i)); -- } else { -+ } else if (count) { - memcpy(data, static_cast<const void*>(vector.constData()), count * sizeof(T)); - } - } --- -2.36.0 - -From 2dc624d1f7771d4e93ad7f5293fb43cf539b1ca4 Mon Sep 17 00:00:00 2001 -From: Ulf Hermann <ulf.hermann@qt.io> -Date: Thu, 3 Feb 2022 10:02:06 +0100 -Subject: [PATCH 15/19] V4: Do not call dtor of an object we continue to use - -After destroyObject(), the QObjectWrapper is still alive. We might use -its heap object again. Furthermore, the Heap::QObjectWrapper dtor does -not actually do anything defined. What we want to do here is clear the -QObject pointer because we've just gotten rid of the QObject. There is a -method for that: Heap::QObjectWrapper::destroy(). +2.49.0 -Finally, the internalClass must never ever be nullptr. Assert on that -rather than checking it. - -Pick-to: 5.15 6.2 6.3 -Task-number: QTBUG-100431 -Change-Id: I794a295c182b2ed4ba80673f58d6143c861b7391 -Reviewed-by: Andrei Golubev <andrei.golubev@qt.io> -Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org> -Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io> -(cherry picked from commit 6c197319f34b8098d034f1543eb5feb9d7be54c3) ---- - src/qml/jsruntime/qv4qobjectwrapper.cpp | 5 ++--- - 1 file changed, 2 insertions(+), 3 deletions(-) - -diff --git a/src/qml/jsruntime/qv4qobjectwrapper.cpp b/src/qml/jsruntime/qv4qobjectwrapper.cpp -index 9899c9274e..272b85069f 100644 ---- a/src/qml/jsruntime/qv4qobjectwrapper.cpp -+++ b/src/qml/jsruntime/qv4qobjectwrapper.cpp -@@ -1160,8 +1160,7 @@ void Heap::QObjectWrapper::markObjects(Heap::Base *that, QV4::MarkStack *markSta - void QObjectWrapper::destroyObject(bool lastCall) - { - Heap::QObjectWrapper *h = d(); -- if (!h->internalClass) -- return; // destroyObject already got called -+ Q_ASSERT(h->internalClass); - - if (h->object()) { - QQmlData *ddata = QQmlData::get(h->object(), false); -@@ -1191,7 +1190,7 @@ void QObjectWrapper::destroyObject(bool lastCall) - } - } - -- h->~Data(); -+ h->destroy(); - } - - --- -2.36.0 - -From 5eee7419f55c592a24d9c7746df0f197d8f0a71d Mon Sep 17 00:00:00 2001 +From 34752ab840ef2dc3bce327fe39c356f4b909f22a Mon Sep 17 00:00:00 2001 From: Vlad Zahorodnii <vlad.zahorodnii@kde.org> Date: Sat, 29 Jan 2022 21:59:33 +0200 -Subject: [PATCH 16/19] Make sure QQuickWidget and its offscreen window's +Subject: [PATCH 05/21] Make sure QQuickWidget and its offscreen window's screens are always in sync By default, the offscreen window is placed on the primary screen. @@ -1427,7 +367,7 @@ Reviewed-by: Laszlo Agocs <laszlo.agocs@qt.io> 1 file changed, 11 insertions(+), 15 deletions(-) diff --git a/src/quickwidgets/qquickwidget.cpp b/src/quickwidgets/qquickwidget.cpp -index 39780f8de3..223d91f579 100644 +index cf021d9a7c..c791f209cf 100644 --- a/src/quickwidgets/qquickwidget.cpp +++ b/src/quickwidgets/qquickwidget.cpp @@ -106,6 +106,7 @@ void QQuickWidgetPrivate::init(QQmlEngine* e) @@ -1449,7 +389,7 @@ index 39780f8de3..223d91f579 100644 QOpenGLContext *shareContext = qt_gl_global_share_context(); if (!shareContext) shareContext = QWidgetPrivate::get(q->window())->shareContext(); -@@ -1520,19 +1519,16 @@ bool QQuickWidget::event(QEvent *e) +@@ -1527,19 +1526,16 @@ bool QQuickWidget::event(QEvent *e) d->handleWindowChange(); break; @@ -1477,7 +417,7 @@ index 39780f8de3..223d91f579 100644 if (d->useSoftwareRenderer #if QT_CONFIG(opengl) -@@ -1545,7 +1541,7 @@ bool QQuickWidget::event(QEvent *e) +@@ -1552,7 +1548,7 @@ bool QQuickWidget::event(QEvent *e) d->render(true); } break; @@ -1487,238 +427,1539 @@ index 39780f8de3..223d91f579 100644 case QEvent::Move: d->updatePosition(); -- -2.36.0 +2.49.0 -From 51efb2ed2f071beda188270a23ac450fe4b318f7 Mon Sep 17 00:00:00 2001 -From: Fabian Kosmale <fabian.kosmale@qt.io> -Date: Wed, 4 May 2022 09:10:54 +0200 -Subject: [PATCH 17/19] QQuickItem: Guard against cycles in - nextPrevItemInTabFocusChain +From f2659326a01cd58ebd04b7590e486eb7d2830b28 Mon Sep 17 00:00:00 2001 +From: Fushan Wen <qydwhotmail@gmail.com> +Date: Tue, 1 Nov 2022 22:35:24 +0800 +Subject: [PATCH 06/21] Don't convert QByteArray in `startDrag` + +QMimeData::setData expects the provided data to contain the correctly +encoded QByteArray, so if the variant contains a QByteArray, then take +it as is to avoid data loss. + +If the variant is not already a byte array, then we ideally would make +sure that the mime type (i.e. the key of the map) and the QVariant's +type are compatible (image/png with a QImage works; text/plain with a +QImage does not). This changes behavior and needs to be a follow-up +commit. + +Fixes: QTBUG-71922 +Change-Id: I9b9f10fd332e1f9568f6835a69a1c359457f823c +Reviewed-by: Volker Hilsheimer <volker.hilsheimer@qt.io> +(cherry picked from commit 062f9bf57657b54dc708015ec5fed3c89e5cc3ca) +Reviewed-by: Qt Cherry-pick Bot <cherrypick_bot@qt-project.org> + + +(cherry picked from commit 22de23c4bb9ac5e2c545e9de3149a7d4f8edd5ee) +--- + src/quick/items/qquickdrag.cpp | 12 +++++++++--- + 1 file changed, 9 insertions(+), 3 deletions(-) + +diff --git a/src/quick/items/qquickdrag.cpp b/src/quick/items/qquickdrag.cpp +index 8321fcfeed..3b50370355 100644 +--- a/src/quick/items/qquickdrag.cpp ++++ b/src/quick/items/qquickdrag.cpp +@@ -481,7 +481,9 @@ void QQuickDragAttached::setKeys(const QStringList &keys) + \qmlattachedproperty stringlist QtQuick::Drag::mimeData + \since 5.2 + +- This property holds a map of mimeData that is used during startDrag. ++ This property holds a map from mime type to data that is used during startDrag. ++ The mime data needs to be a \c string, or an \c ArrayBuffer with the data encoded ++ according to the mime type. + */ + + QVariantMap QQuickDragAttached::mimeData() const +@@ -766,8 +768,12 @@ Qt::DropAction QQuickDragAttachedPrivate::startDrag(Qt::DropActions supportedAct + QDrag *drag = new QDrag(source ? source : q); + QMimeData *mimeData = new QMimeData(); + +- for (auto it = externalMimeData.cbegin(), end = externalMimeData.cend(); it != end; ++it) +- mimeData->setData(it.key(), it.value().toString().toUtf8()); ++ for (auto it = externalMimeData.cbegin(), end = externalMimeData.cend(); it != end; ++it) { ++ if (it.value().typeId() == QMetaType::QByteArray) ++ mimeData->setData(it.key(), it.value().toByteArray()); ++ else ++ mimeData->setData(it.key(), it.value().toString().toUtf8()); ++ } + + drag->setMimeData(mimeData); + if (pixmapLoader.isReady()) { +-- +2.49.0 + +From 771b2ebea68e8f4c33a9d440c20d3dd1157670f6 Mon Sep 17 00:00:00 2001 +From: Hannah von Reth <vonreth@kde.org> +Date: Sat, 5 Nov 2022 18:48:41 +0100 +Subject: [PATCH 07/21] Fix build after + 95290f66b806a307b8da1f72f8fc2c69801933d0 + +--- + src/quick/items/qquickdrag.cpp | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/src/quick/items/qquickdrag.cpp b/src/quick/items/qquickdrag.cpp +index 3b50370355..383078b3b9 100644 +--- a/src/quick/items/qquickdrag.cpp ++++ b/src/quick/items/qquickdrag.cpp +@@ -769,7 +769,7 @@ Qt::DropAction QQuickDragAttachedPrivate::startDrag(Qt::DropActions supportedAct + QMimeData *mimeData = new QMimeData(); + + for (auto it = externalMimeData.cbegin(), end = externalMimeData.cend(); it != end; ++it) { +- if (it.value().typeId() == QMetaType::QByteArray) ++ if (static_cast<QMetaType::Type>(it.value().type()) == QMetaType::QByteArray) + mimeData->setData(it.key(), it.value().toByteArray()); + else + mimeData->setData(it.key(), it.value().toString().toUtf8()); +-- +2.49.0 + +From 295c5e9912edf5976f2035b22baa5f37af40c7c2 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Morten=20Johan=20S=C3=B8rvig?= <morten.sorvig@qt.io> +Date: Fri, 7 May 2021 10:07:50 +0200 +Subject: [PATCH 08/21] Implement accessibility for QQuickWidget MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit -nextPrevItemInTabFocusChain already had a check to prevent running into -cycles, it would however only detect if we reached the original item. If -our cycle instead would loop between reachable items without ever -returning to the initial one, as in the diagram below, then we would -never terminate the loop. - - /-->other item<---next item -initial-item \ ^ - \ | - --->different item - -To prevent this from happening, we keep track of all items we've seen so -far. One last complications arises due to the fact that we do visit the -parent twice under some cicrcumstances, but we already have the skip -variable to indicate that case – we simply skip the duplicate check if -it is set to true. - -Pick-to: 6.2 6.3 -Fixes: QTBUG-87190 -Change-Id: I1449a7ebf8f325f00c296e8a8db4360faf1049e4 +The accessibility tree for the Qt Quick content should +be rooted at the QQuickWidget, and not at the offscreen +QQuickWindow. + +For this to be the case, several things must happen: + - QQuickWindow must not report the child interfaces + - QQuickWidget must report the child interfaces + - The child interfaces must report the QQuickWidget as the parent + +Create accessibility interfaces for QQuickWidget and +and QQuickWigetOffscreenWindow (which now gets a proper +subclass), where the QQuickWidget interface reports +the child interfaces and the QQuickWigetOffscreenWindow +reports no children + +Change the code in QAccessibleQuickItem to use the +true (visible) window, where needed. + +Fixes: QTBUG-67290 +Change-Id: I387d0ef711138d248a8dd16eefc9839499b35eeb +Reviewed-by: Jan Arve Sæther <jan-arve.saether@qt.io> Reviewed-by: Volker Hilsheimer <volker.hilsheimer@qt.io> -(cherry picked from commit e74bcf751495d9fe27efd195bc04e2a6ae6732a4) +(cherry picked from commit 41926e08d73ea6c4bbfc87a1dd52d2cdbc435c27) +--- + src/quick/accessible/qaccessiblequickitem.cpp | 29 +++-- + src/quick/accessible/qaccessiblequickview_p.h | 2 +- + src/quickwidgets/qaccessiblequickwidget.cpp | 110 ++++++++++++++++++ + src/quickwidgets/qaccessiblequickwidget.h | 84 +++++++++++++ + .../qaccessiblequickwidgetfactory.cpp | 60 ++++++++++ + .../qaccessiblequickwidgetfactory_p.h | 66 +++++++++++ + src/quickwidgets/qquickwidget.cpp | 18 ++- + src/quickwidgets/qquickwidget_p.h | 8 ++ + src/quickwidgets/quickwidgets.pro | 8 +- + 9 files changed, 368 insertions(+), 17 deletions(-) + create mode 100644 src/quickwidgets/qaccessiblequickwidget.cpp + create mode 100644 src/quickwidgets/qaccessiblequickwidget.h + create mode 100644 src/quickwidgets/qaccessiblequickwidgetfactory.cpp + create mode 100644 src/quickwidgets/qaccessiblequickwidgetfactory_p.h + +diff --git a/src/quick/accessible/qaccessiblequickitem.cpp b/src/quick/accessible/qaccessiblequickitem.cpp +index 36b65f906c..4d9e307a48 100644 +--- a/src/quick/accessible/qaccessiblequickitem.cpp ++++ b/src/quick/accessible/qaccessiblequickitem.cpp +@@ -46,6 +46,7 @@ + #include "QtQuick/private/qquicktextinput_p.h" + #include "QtQuick/private/qquickaccessibleattached_p.h" + #include "QtQuick/qquicktextdocument.h" ++#include "QtQuick/qquickrendercontrol.h" + QT_BEGIN_NAMESPACE + + #if QT_CONFIG(accessibility) +@@ -57,7 +58,19 @@ QAccessibleQuickItem::QAccessibleQuickItem(QQuickItem *item) + + QWindow *QAccessibleQuickItem::window() const + { +- return item()->window(); ++ QQuickWindow *window = item()->window(); ++ ++ // For QQuickWidget the above window will be the offscreen QQuickWindow, ++ // which is not a part of the accessibility tree. Detect this case and ++ // return the window for the QQuickWidget instead. ++ if (window && !window->handle()) { ++ if (QQuickRenderControl *renderControl = QQuickWindowPrivate::get(window)->renderControl) { ++ if (QWindow *renderWindow = renderControl->renderWindow(nullptr)) ++ return renderWindow; ++ } ++ } ++ ++ return window; + } + + int QAccessibleQuickItem::childCount() const +@@ -113,19 +126,15 @@ QAccessibleInterface *QAccessibleQuickItem::childAt(int x, int y) const + QAccessibleInterface *QAccessibleQuickItem::parent() const + { + QQuickItem *parent = item()->parentItem(); +- QQuickWindow *window = item()->window(); +- QQuickItem *ci = window ? window->contentItem() : nullptr; ++ QQuickWindow *itemWindow = item()->window(); ++ QQuickItem *ci = itemWindow ? itemWindow->contentItem() : nullptr; + while (parent && !QQuickItemPrivate::get(parent)->isAccessible && parent != ci) + parent = parent->parentItem(); + + if (parent) { + if (parent == ci) { +- // Jump out to the scene widget if the parent is the root item. +- // There are two root items, QQuickWindow::rootItem and +- // QQuickView::declarativeRoot. The former is the true root item, +- // but is not a part of the accessibility tree. Check if we hit +- // it here and return an interface for the scene instead. +- return QAccessible::queryAccessibleInterface(window); ++ // Jump out to the window if the parent is the root item ++ return QAccessible::queryAccessibleInterface(window()); + } else { + while (parent && !parent->d_func()->isAccessible) + parent = parent->parentItem(); +@@ -193,7 +202,7 @@ QAccessible::State QAccessibleQuickItem::state() const + QRect viewRect_ = viewRect(); + QRect itemRect = rect(); + +- if (viewRect_.isNull() || itemRect.isNull() || !item()->window() || !item()->window()->isVisible() ||!item()->isVisible() || qFuzzyIsNull(item()->opacity())) ++ if (viewRect_.isNull() || itemRect.isNull() || !window() || !window()->isVisible() ||!item()->isVisible() || qFuzzyIsNull(item()->opacity())) + state.invisible = true; + if (!viewRect_.intersects(itemRect)) + state.offscreen = true; +diff --git a/src/quick/accessible/qaccessiblequickview_p.h b/src/quick/accessible/qaccessiblequickview_p.h +index 39ffcaf39c..8baa01330c 100644 +--- a/src/quick/accessible/qaccessiblequickview_p.h ++++ b/src/quick/accessible/qaccessiblequickview_p.h +@@ -58,7 +58,7 @@ QT_BEGIN_NAMESPACE + + #if QT_CONFIG(accessibility) + +-class QAccessibleQuickWindow : public QAccessibleObject ++class Q_QUICK_EXPORT QAccessibleQuickWindow : public QAccessibleObject + { + public: + QAccessibleQuickWindow(QQuickWindow *object); +diff --git a/src/quickwidgets/qaccessiblequickwidget.cpp b/src/quickwidgets/qaccessiblequickwidget.cpp +new file mode 100644 +index 0000000000..6f04d6693f +--- /dev/null ++++ b/src/quickwidgets/qaccessiblequickwidget.cpp +@@ -0,0 +1,110 @@ ++/**************************************************************************** ++** ++** Copyright (C) 2021 The Qt Company Ltd. ++** Contact: https://www.qt.io/licensing/ ++** ++** This file is part of the QtQuick module of the Qt Toolkit. ++** ++** $QT_BEGIN_LICENSE:LGPL$ ++** 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 Lesser General Public License Usage ++** Alternatively, this file may be used under the terms of the GNU Lesser ++** General Public License version 3 as published by the Free Software ++** Foundation and appearing in the file LICENSE.LGPL3 included in the ++** packaging of this file. Please review the following information to ++** ensure the GNU Lesser General Public License version 3 requirements ++** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ++** ++** GNU General Public License Usage ++** Alternatively, this file may be used under the terms of the GNU ++** General Public License version 2.0 or (at your option) the GNU General ++** Public license version 3 or any later version approved by the KDE Free ++** Qt Foundation. The licenses are as published by the Free Software ++** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ++** 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-2.0.html and ++** https://www.gnu.org/licenses/gpl-3.0.html. ++** ++** $QT_END_LICENSE$ ++** ++****************************************************************************/ ++ ++#include "qaccessiblequickwidget.h" ++ ++#include "qquickwidget_p.h" ++ ++QT_BEGIN_NAMESPACE ++ ++#if QT_CONFIG(accessibility) ++ ++QAccessibleQuickWidget::QAccessibleQuickWidget(QQuickWidget* widget) ++: QAccessibleWidget(widget) ++, m_accessibleWindow(QQuickWidgetPrivate::get(widget)->offscreenWindow) ++{ ++ // NOTE: m_accessibleWindow is a QAccessibleQuickWindow, and not a ++ // QAccessibleQuickWidgetOffscreenWindow (defined below). This means ++ // it will return the Quick item child interfaces, which is what's needed here ++ // (unlike QAccessibleQuickWidgetOffscreenWindow, which will report 0 children). ++} ++ ++QAccessibleInterface *QAccessibleQuickWidget::child(int index) const ++{ ++ return m_accessibleWindow.child(index); ++} ++ ++int QAccessibleQuickWidget::childCount() const ++{ ++ return m_accessibleWindow.childCount(); ++} ++ ++int QAccessibleQuickWidget::indexOfChild(const QAccessibleInterface *iface) const ++{ ++ return m_accessibleWindow.indexOfChild(iface); ++} ++ ++QAccessibleInterface *QAccessibleQuickWidget::childAt(int x, int y) const ++{ ++ return m_accessibleWindow.childAt(x, y); ++} ++ ++QAccessibleQuickWidgetOffscreenWindow::QAccessibleQuickWidgetOffscreenWindow(QQuickWindow *window) ++:QAccessibleQuickWindow(window) ++{ ++ ++} ++ ++QAccessibleInterface *QAccessibleQuickWidgetOffscreenWindow::child(int index) const ++{ ++ Q_UNUSED(index); ++ return nullptr; ++} ++ ++int QAccessibleQuickWidgetOffscreenWindow::childCount() const ++{ ++ return 0; ++} ++ ++int QAccessibleQuickWidgetOffscreenWindow::indexOfChild(const QAccessibleInterface *iface) const ++{ ++ Q_UNUSED(iface); ++ return -1; ++} ++ ++QAccessibleInterface *QAccessibleQuickWidgetOffscreenWindow::QAccessibleQuickWidgetOffscreenWindow::childAt(int x, int y) const ++{ ++ Q_UNUSED(x); ++ Q_UNUSED(y); ++ return nullptr; ++} ++ ++#endif // accessibility ++ ++QT_END_NAMESPACE +diff --git a/src/quickwidgets/qaccessiblequickwidget.h b/src/quickwidgets/qaccessiblequickwidget.h +new file mode 100644 +index 0000000000..1f52c78c46 +--- /dev/null ++++ b/src/quickwidgets/qaccessiblequickwidget.h +@@ -0,0 +1,84 @@ ++/**************************************************************************** ++** ++** Copyright (C) 2021 The Qt Company Ltd. ++** Contact: https://www.qt.io/licensing/ ++** ++** This file is part of the QtQuick module of the Qt Toolkit. ++** ++** $QT_BEGIN_LICENSE:LGPL$ ++** 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 Lesser General Public License Usage ++** Alternatively, this file may be used under the terms of the GNU Lesser ++** General Public License version 3 as published by the Free Software ++** Foundation and appearing in the file LICENSE.LGPL3 included in the ++** packaging of this file. Please review the following information to ++** ensure the GNU Lesser General Public License version 3 requirements ++** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ++** ++** GNU General Public License Usage ++** Alternatively, this file may be used under the terms of the GNU ++** General Public License version 2.0 or (at your option) the GNU General ++** Public license version 3 or any later version approved by the KDE Free ++** Qt Foundation. The licenses are as published by the Free Software ++** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ++** 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-2.0.html and ++** https://www.gnu.org/licenses/gpl-3.0.html. ++** ++** $QT_END_LICENSE$ ++** ++****************************************************************************/ ++ ++#ifndef QACCESSIBLEQUICKWIDGET_H ++#define QACCESSIBLEQUICKWIDGET_H ++ ++#include "qquickwidget.h" ++#include <QtWidgets/qaccessiblewidget.h> ++ ++#include <private/qaccessiblequickview_p.h> ++ ++QT_BEGIN_NAMESPACE ++ ++#if QT_CONFIG(accessibility) ++ ++// These classes implement the QQuickWiget accessibility switcharoo, ++// where the child items of the QQuickWidgetOffscreenWindow are reported ++// as child accessible interfaces of the QAccessibleQuickWidget. ++class QAccessibleQuickWidget: public QAccessibleWidget ++{ ++public: ++ QAccessibleQuickWidget(QQuickWidget* widget); ++ ++ QAccessibleInterface *child(int index) const override; ++ int childCount() const override; ++ int indexOfChild(const QAccessibleInterface *iface) const override; ++ QAccessibleInterface *childAt(int x, int y) const override; ++ ++private: ++ QAccessibleQuickWindow m_accessibleWindow; ++ Q_DISABLE_COPY(QAccessibleQuickWidget) ++}; ++ ++class QAccessibleQuickWidgetOffscreenWindow: public QAccessibleQuickWindow ++{ ++public: ++ QAccessibleQuickWidgetOffscreenWindow(QQuickWindow *window); ++ QAccessibleInterface *child(int index) const override; ++ int childCount() const override; ++ int indexOfChild(const QAccessibleInterface *iface) const override; ++ QAccessibleInterface *childAt(int x, int y) const override; ++}; ++ ++#endif // accessibility ++ ++QT_END_NAMESPACE ++ ++#endif +diff --git a/src/quickwidgets/qaccessiblequickwidgetfactory.cpp b/src/quickwidgets/qaccessiblequickwidgetfactory.cpp +new file mode 100644 +index 0000000000..3756d0c27c +--- /dev/null ++++ b/src/quickwidgets/qaccessiblequickwidgetfactory.cpp +@@ -0,0 +1,60 @@ ++/**************************************************************************** ++** ++** Copyright (C) 2021 The Qt Company Ltd. ++** Contact: https://www.qt.io/licensing/ ++** ++** This file is part of the QtQuick module of the Qt Toolkit. ++** ++** $QT_BEGIN_LICENSE:LGPL$ ++** 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 Lesser General Public License Usage ++** Alternatively, this file may be used under the terms of the GNU Lesser ++** General Public License version 3 as published by the Free Software ++** Foundation and appearing in the file LICENSE.LGPL3 included in the ++** packaging of this file. Please review the following information to ++** ensure the GNU Lesser General Public License version 3 requirements ++** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ++** ++** GNU General Public License Usage ++** Alternatively, this file may be used under the terms of the GNU ++** General Public License version 2.0 or (at your option) the GNU General ++** Public license version 3 or any later version approved by the KDE Free ++** Qt Foundation. The licenses are as published by the Free Software ++** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ++** 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-2.0.html and ++** https://www.gnu.org/licenses/gpl-3.0.html. ++** ++** $QT_END_LICENSE$ ++** ++****************************************************************************/ ++ ++#include "qaccessiblequickwidgetfactory_p.h" ++#include "qaccessiblequickwidget.h" ++ ++QT_BEGIN_NAMESPACE ++ ++#if QT_CONFIG(accessibility) ++ ++QAccessibleInterface *qAccessibleQuickWidgetFactory(const QString &classname, QObject *object) ++{ ++ if (classname == QLatin1String("QQuickWidget")) { ++ return new QAccessibleQuickWidget(qobject_cast<QQuickWidget *>(object)); ++ } else if (classname == QLatin1String("QQuickWidgetOffscreenWindow")) { ++ return new QAccessibleQuickWidgetOffscreenWindow(qobject_cast<QQuickWindow *>(object)); ++ } ++ return 0; ++} ++ ++#endif // accessibility ++ ++QT_END_NAMESPACE ++ +diff --git a/src/quickwidgets/qaccessiblequickwidgetfactory_p.h b/src/quickwidgets/qaccessiblequickwidgetfactory_p.h +new file mode 100644 +index 0000000000..8c63b09f81 +--- /dev/null ++++ b/src/quickwidgets/qaccessiblequickwidgetfactory_p.h +@@ -0,0 +1,66 @@ ++/**************************************************************************** ++** ++** Copyright (C) 2021 The Qt Company Ltd. ++** Contact: https://www.qt.io/licensing/ ++** ++** This file is part of the QtQuick module of the Qt Toolkit. ++** ++** $QT_BEGIN_LICENSE:LGPL$ ++** 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 Lesser General Public License Usage ++** Alternatively, this file may be used under the terms of the GNU Lesser ++** General Public License version 3 as published by the Free Software ++** Foundation and appearing in the file LICENSE.LGPL3 included in the ++** packaging of this file. Please review the following information to ++** ensure the GNU Lesser General Public License version 3 requirements ++** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ++** ++** GNU General Public License Usage ++** Alternatively, this file may be used under the terms of the GNU ++** General Public License version 2.0 or (at your option) the GNU General ++** Public license version 3 or any later version approved by the KDE Free ++** Qt Foundation. The licenses are as published by the Free Software ++** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ++** 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-2.0.html and ++** https://www.gnu.org/licenses/gpl-3.0.html. ++** ++** $QT_END_LICENSE$ ++** ++****************************************************************************/ ++ ++#include <QtGui/qaccessible.h> ++ ++#ifndef QACCESSIBLEQUICKWIDGETFACTORY_H ++#define QACCESSIBLEQUICKWIDGETFACTORY_H ++ ++// ++// W A R N I N G ++// ------------- ++// ++// This file is not part of the Qt API. It exists purely as an ++// implementation detail. This header file may change from version to ++// version without notice, or even be removed. ++// ++// We mean it. ++// ++ ++QT_BEGIN_NAMESPACE ++ ++#if QT_CONFIG(accessibility) ++ ++QAccessibleInterface *qAccessibleQuickWidgetFactory(const QString &classname, QObject *object); ++ ++#endif ++ ++QT_END_NAMESPACE ++ ++#endif +diff --git a/src/quickwidgets/qquickwidget.cpp b/src/quickwidgets/qquickwidget.cpp +index c791f209cf..b0117683f7 100644 +--- a/src/quickwidgets/qquickwidget.cpp ++++ b/src/quickwidgets/qquickwidget.cpp +@@ -39,6 +39,7 @@ + + #include "qquickwidget.h" + #include "qquickwidget_p.h" ++#include "qaccessiblequickwidgetfactory_p.h" + + #include "private/qquickwindow_p.h" + #include "private/qquickitem_p.h" +@@ -75,9 +76,16 @@ + + QT_BEGIN_NAMESPACE + ++QQuickWidgetOffscreenWindow::QQuickWidgetOffscreenWindow(QQuickWindowPrivate &dd, QQuickRenderControl *control) ++:QQuickWindow(dd, control) ++{ ++ setTitle(QString::fromLatin1("Offscreen")); ++ setObjectName(QString::fromLatin1("QQuickOffScreenWindow")); ++} ++ + // override setVisble to prevent accidental offscreen window being created + // by base class. +-class QQuickOffcreenWindowPrivate: public QQuickWindowPrivate { ++class QQuickWidgetOffscreenWindowPrivate: public QQuickWindowPrivate { + public: + void setVisible(bool visible) override { + Q_Q(QWindow); +@@ -105,10 +113,8 @@ void QQuickWidgetPrivate::init(QQmlEngine* e) + Q_Q(QQuickWidget); + + renderControl = new QQuickWidgetRenderControl(q); +- offscreenWindow = new QQuickWindow(*new QQuickOffcreenWindowPrivate(),renderControl); ++ offscreenWindow = new QQuickWidgetOffscreenWindow(*new QQuickWidgetOffscreenWindowPrivate(), renderControl); + offscreenWindow->setScreen(q->screen()); +- offscreenWindow->setTitle(QString::fromLatin1("Offscreen")); +- offscreenWindow->setObjectName(QString::fromLatin1("QQuickOffScreenWindow")); + // Do not call create() on offscreenWindow. + + // Check if the Software Adaptation is being used +@@ -139,6 +145,10 @@ void QQuickWidgetPrivate::init(QQmlEngine* e) + QWidget::connect(offscreenWindow, &QQuickWindow::focusObjectChanged, q, &QQuickWidget::propagateFocusObjectChanged); + QObject::connect(renderControl, SIGNAL(renderRequested()), q, SLOT(triggerUpdate())); + QObject::connect(renderControl, SIGNAL(sceneChanged()), q, SLOT(triggerUpdate())); ++ ++#if QT_CONFIG(accessibility) ++ QAccessible::installFactory(&qAccessibleQuickWidgetFactory); ++#endif + } + + void QQuickWidgetPrivate::ensureEngine() const +diff --git a/src/quickwidgets/qquickwidget_p.h b/src/quickwidgets/qquickwidget_p.h +index 881f7f9220..1a946bcc71 100644 +--- a/src/quickwidgets/qquickwidget_p.h ++++ b/src/quickwidgets/qquickwidget_p.h +@@ -148,6 +148,14 @@ public: + bool forceFullUpdate; + }; + ++class QQuickWidgetOffscreenWindow: public QQuickWindow ++{ ++ Q_OBJECT ++ ++public: ++ QQuickWidgetOffscreenWindow(QQuickWindowPrivate &dd, QQuickRenderControl *control); ++}; ++ + QT_END_NAMESPACE + + #endif // QQuickWidget_P_H +diff --git a/src/quickwidgets/quickwidgets.pro b/src/quickwidgets/quickwidgets.pro +index 2438e577ae..f46deb54ac 100644 +--- a/src/quickwidgets/quickwidgets.pro ++++ b/src/quickwidgets/quickwidgets.pro +@@ -7,9 +7,13 @@ DEFINES += QT_NO_URL_CAST_FROM_STRING QT_NO_INTEGER_EVENT_COORDINATES QT_NO_FO + HEADERS += \ + qquickwidget.h \ + qquickwidget_p.h \ +- qtquickwidgetsglobal.h ++ qtquickwidgetsglobal.h \ ++ qaccessiblequickwidget.h \ ++ qaccessiblequickwidgetfactory_p.h + + SOURCES += \ +- qquickwidget.cpp ++ qquickwidget.cpp \ ++ qaccessiblequickwidget.cpp \ ++ qaccessiblequickwidgetfactory.cpp + + load(qt_module) +-- +2.49.0 + +From 646152bc85f1586a2e958d5279a90213e4a7d658 Mon Sep 17 00:00:00 2001 +From: Fushan Wen <qydwhotmail@gmail.com> +Date: Sat, 5 Nov 2022 01:44:30 +0800 +Subject: [PATCH 09/21] Send ObjectShow event for visible components after + initialized +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Currently ObjectShow event is only sent when the visible property +changes from false to true, but for items with the notification +accessible role, a screen reader like Orca needs to receive an +ObjectShow event to read the notification, so also send the event after +a component is initialized. + +See also: https://gitlab.gnome.org/GNOME/orca/-/merge_requests/134 + +Pick-to: 6.4 +Change-Id: I626594b65ffe4d0582dcee9f489df0c2c63e53b7 +Reviewed-by: Jan Arve Sæther <jan-arve.saether@qt.io> +(cherry picked from commit 9a4f2d23ecec2c7ff19f83cff28df6b97e3fda98) --- - src/quick/items/qquickitem.cpp | 7 ++++++- - .../data/activeFocusOnTab_infiniteLoop3.qml | 13 +++++++++++++ - tests/auto/quick/qquickitem2/tst_qquickitem.cpp | 12 ++++++++++++ - 3 files changed, 31 insertions(+), 1 deletion(-) - create mode 100644 tests/auto/quick/qquickitem2/data/activeFocusOnTab_infiniteLoop3.qml + src/quick/items/qquickitem.cpp | 7 +++++++ + 1 file changed, 7 insertions(+) diff --git a/src/quick/items/qquickitem.cpp b/src/quick/items/qquickitem.cpp -index 497672b497..81b0db0b69 100644 +index c655b4c327..1e9d3a5cb7 100644 --- a/src/quick/items/qquickitem.cpp +++ b/src/quick/items/qquickitem.cpp -@@ -59,6 +59,7 @@ - #include <QtCore/private/qnumeric_p.h> - #include <QtGui/qpa/qplatformtheme.h> - #include <QtCore/qloggingcategory.h> -+#include <QtCore/private/qduplicatetracker_p.h> - - #include <private/qqmlglobal_p.h> - #include <private/qqmlengine_p.h> -@@ -2520,6 +2521,7 @@ QQuickItem* QQuickItemPrivate::nextPrevItemInTabFocusChain(QQuickItem *item, boo - QQuickItem *current = item; - qCDebug(DBG_FOCUS) << "QQuickItemPrivate::nextPrevItemInTabFocusChain: startItem:" << startItem; - qCDebug(DBG_FOCUS) << "QQuickItemPrivate::nextPrevItemInTabFocusChain: firstFromItem:" << firstFromItem; -+ QDuplicateTracker<QQuickItem *> cycleDetector; - do { - qCDebug(DBG_FOCUS) << "QQuickItemPrivate::nextPrevItemInTabFocusChain: current:" << current; - qCDebug(DBG_FOCUS) << "QQuickItemPrivate::nextPrevItemInTabFocusChain: from:" << from; -@@ -2586,7 +2588,10 @@ QQuickItem* QQuickItemPrivate::nextPrevItemInTabFocusChain(QQuickItem *item, boo - // traversed all of the chain (by compare the [current] item with [startItem]) - // Since the [startItem] might be promoted to its parent if it is invisible, - // we still have to check [current] item with original start item -- if ((current == startItem || current == originalStartItem) && from == firstFromItem) { -+ // We might also run into a cycle before we reach firstFromItem again -+ // but note that we have to ignore current if we are meant to skip it -+ if (((current == startItem || current == originalStartItem) && from == firstFromItem) || -+ (!skip && cycleDetector.hasSeen(current))) { - // wrapped around, avoid endless loops - if (item == contentItem) { - qCDebug(DBG_FOCUS) << "QQuickItemPrivate::nextPrevItemInTabFocusChain: looped, return contentItem"; -diff --git a/tests/auto/quick/qquickitem2/data/activeFocusOnTab_infiniteLoop3.qml b/tests/auto/quick/qquickitem2/data/activeFocusOnTab_infiniteLoop3.qml -new file mode 100644 -index 0000000000..889e480f3b ---- /dev/null -+++ b/tests/auto/quick/qquickitem2/data/activeFocusOnTab_infiniteLoop3.qml -@@ -0,0 +1,13 @@ -+import QtQuick 2.6 +@@ -5126,6 +5126,13 @@ void QQuickItem::componentComplete() + d->addToDirtyList(); + QQuickWindowPrivate::get(d->window)->dirtyItem(this); + } + -+Item { -+ visible: true -+ Item { -+ visible: false -+ Item { -+ objectName: "hiddenChild" -+ activeFocusOnTab: true -+ focus: true -+ } ++#if QT_CONFIG(accessibility) ++ if (d->isAccessible && d->effectiveVisible) { ++ QAccessibleEvent ev(this, QAccessible::ObjectShow); ++ QAccessible::updateAccessibility(&ev); + } -+} -diff --git a/tests/auto/quick/qquickitem2/tst_qquickitem.cpp b/tests/auto/quick/qquickitem2/tst_qquickitem.cpp -index f65650cf9c..eeff768bb4 100644 ---- a/tests/auto/quick/qquickitem2/tst_qquickitem.cpp -+++ b/tests/auto/quick/qquickitem2/tst_qquickitem.cpp -@@ -66,6 +66,7 @@ private slots: - void activeFocusOnTab10(); - void activeFocusOnTab_infiniteLoop_data(); - void activeFocusOnTab_infiniteLoop(); -+ void activeFocusOnTab_infiniteLoopControls(); - - void nextItemInFocusChain(); - void nextItemInFocusChain2(); -@@ -1055,6 +1056,17 @@ void tst_QQuickItem::activeFocusOnTab_infiniteLoop() - QCOMPARE(item, window->rootObject()); ++#endif + } + + QQuickStateGroup *QQuickItemPrivate::_states() +-- +2.49.0 + +From fa676c3d3a33ef8fe989aa0b69b447a5ded72139 Mon Sep 17 00:00:00 2001 +From: Volker Hilsheimer <volker.hilsheimer@qt.io> +Date: Wed, 9 Nov 2022 15:34:11 +0100 +Subject: [PATCH 10/21] QQuickItem: avoid emitting signals during destruction + +If a QQuickItem is in the QQuickItem destructor, then it is both unsafe +and unnecessary to emit property change notifications. Connected code +can no longer rely on the state of the emitting object - if it was +originally a subclass of QQuickItem, then those subclass destructors +will already have run. And the QQuickItem destructor will also have +partially run, leaving the object in an undefined state. + +Add a flag that we set to true at the top of ~QQuickItem, and don't emit +visibleChildrenChanged, parentChanged, visibleChanged, and +childrenChanged for items that are partially destroyed already. + +[ChangeLog][Qt Quick][QQuickItem] QQuickItem no longer emits change +notifications for the parent, children, visible, and visibleChildren +properties while it is being destroyed. + +Task-number: QTBUG-107850 +Change-Id: I36ea98842c89ad89fcc1c4a328d138f66f2a0446 +Reviewed-by: Shawn Rutledge <shawn.rutledge@qt.io> +Reviewed-by: Mitch Curtis <mitch.curtis@qt.io> +(cherry picked from commit 74873324bdf3399753f9fcaf7461c0e00df628b1) +--- + src/quick/items/qquickitem.cpp | 21 +++++++++++++-------- + src/quick/items/qquickitem_p.h | 1 + + 2 files changed, 14 insertions(+), 8 deletions(-) + +diff --git a/src/quick/items/qquickitem.cpp b/src/quick/items/qquickitem.cpp +index 1e9d3a5cb7..2627494bdd 100644 +--- a/src/quick/items/qquickitem.cpp ++++ b/src/quick/items/qquickitem.cpp +@@ -2328,6 +2328,7 @@ QQuickItem::QQuickItem(QQuickItemPrivate &dd, QQuickItem *parent) + QQuickItem::~QQuickItem() + { + Q_D(QQuickItem); ++ d->inDestructor = true; + + if (d->windowRefCount > 1) + d->windowRefCount = 1; // Make sure window is set to null in next call to derefWindow(). +@@ -2695,9 +2696,8 @@ void QQuickItem::setParentItem(QQuickItem *parentItem) + + const bool wasVisible = isVisible(); + op->removeChild(this); +- if (wasVisible) { ++ if (wasVisible && !op->inDestructor) + emit oldParentItem->visibleChildrenChanged(); +- } + } else if (d->window) { + QQuickWindowPrivate::get(d->window)->parentlessItems.remove(this); + } +@@ -2774,8 +2774,9 @@ void QQuickItem::setParentItem(QQuickItem *parentItem) + + d->itemChange(ItemParentHasChanged, d->parentItem); + +- emit parentChanged(d->parentItem); +- if (isVisible() && d->parentItem) ++ if (!d->inDestructor) ++ emit parentChanged(d->parentItem); ++ if (isVisible() && d->parentItem && !QQuickItemPrivate::get(d->parentItem)->inDestructor) + emit d->parentItem->visibleChildrenChanged(); + } + +@@ -2971,7 +2972,8 @@ void QQuickItemPrivate::removeChild(QQuickItem *child) + + itemChange(QQuickItem::ItemChildRemovedChange, child); + +- emit q->childrenChanged(); ++ if (!inDestructor) ++ emit q->childrenChanged(); + } + + void QQuickItemPrivate::refWindow(QQuickWindow *c) +@@ -3200,6 +3202,7 @@ QQuickItemPrivate::QQuickItemPrivate() + , touchEnabled(false) + #endif + , hasCursorHandler(false) ++ , inDestructor(false) + , dirtyAttributes(0) + , nextDirtyItem(nullptr) + , prevDirtyItem(nullptr) +@@ -6119,9 +6122,11 @@ bool QQuickItemPrivate::setEffectiveVisibleRecur(bool newEffectiveVisible) + QAccessible::updateAccessibility(&ev); + } + #endif +- emit q->visibleChanged(); +- if (childVisibilityChanged) +- emit q->visibleChildrenChanged(); ++ if (!inDestructor) { ++ emit q->visibleChanged(); ++ if (childVisibilityChanged) ++ emit q->visibleChildrenChanged(); ++ } + + return true; // effective visibility DID change + } +diff --git a/src/quick/items/qquickitem_p.h b/src/quick/items/qquickitem_p.h +index d48b551064..6f329bd119 100644 +--- a/src/quick/items/qquickitem_p.h ++++ b/src/quick/items/qquickitem_p.h +@@ -472,6 +472,7 @@ public: + bool replayingPressEvent:1; + bool touchEnabled:1; + bool hasCursorHandler:1; ++ quint32 inDestructor:1; // has entered ~QQuickItem + + enum DirtyType { + TransformOrigin = 0x00000001, +-- +2.49.0 + +From 54a95a6307e0276bdd3e463108501dfb3c4826c1 Mon Sep 17 00:00:00 2001 +From: Harald Sitter <sitter@kde.org> +Date: Mon, 28 Nov 2022 14:59:33 +0100 +Subject: [PATCH 11/21] a11y: track item enabled state +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +disabled items are neither enabled nor focusable + +Change-Id: I4f286c7b85605d5ad6fa787d1f5cfcce1297d268 +Reviewed-by: Volker Hilsheimer <volker.hilsheimer@qt.io> +Reviewed-by: Jan Arve Sæther <jan-arve.saether@qt.io> +(cherry picked from commit 20fd2902a6d7bdb4a3306005d2718ca5a8fef96d) +--- + src/quick/accessible/qaccessiblequickitem.cpp | 4 ++++ + src/quick/items/qquickitem.cpp | 9 +++++++++ + 2 files changed, 13 insertions(+) + +diff --git a/src/quick/accessible/qaccessiblequickitem.cpp b/src/quick/accessible/qaccessiblequickitem.cpp +index 4d9e307a48..99e6eff7c3 100644 +--- a/src/quick/accessible/qaccessiblequickitem.cpp ++++ b/src/quick/accessible/qaccessiblequickitem.cpp +@@ -215,6 +215,10 @@ QAccessible::State QAccessibleQuickItem::state() const + if (role() == QAccessible::EditableText) + if (auto ti = qobject_cast<QQuickTextInput *>(item())) + state.passwordEdit = ti->echoMode() != QQuickTextInput::Normal; ++ if (!item()->isEnabled()) { ++ state.focusable = false; ++ state.disabled = true; ++ } + return state; + } + +diff --git a/src/quick/items/qquickitem.cpp b/src/quick/items/qquickitem.cpp +index 2627494bdd..8b139cb539 100644 +--- a/src/quick/items/qquickitem.cpp ++++ b/src/quick/items/qquickitem.cpp +@@ -6175,6 +6175,15 @@ void QQuickItemPrivate::setEffectiveEnableRecur(QQuickItem *scope, bool newEffec + } + + itemChange(QQuickItem::ItemEnabledHasChanged, effectiveEnable); ++#if QT_CONFIG(accessibility) ++ if (isAccessible) { ++ QAccessible::State changedState; ++ changedState.disabled = true; ++ changedState.focusable = true; ++ QAccessibleStateChangeEvent ev(q, changedState); ++ QAccessible::updateAccessibility(&ev); ++ } ++#endif + emit q->enabledChanged(); } +-- +2.49.0 + +From 37b588026cd2e9b6ab3d4fc374be8583432bbcc9 Mon Sep 17 00:00:00 2001 +From: Fabian Kosmale <fabian.kosmale@qt.io> +Date: Tue, 1 Jun 2021 16:40:44 +0200 +Subject: [PATCH 12/21] Make QaccessibleQuickWidget private API + +Its base class is private API, so it should be private API, too. + +Change-Id: Ic80f841fee19ed0305c60ad5f8e9349a05f09e5e +Reviewed-by: Alexandru Croitor <alexandru.croitor@qt.io> +Reviewed-by: Ulf Hermann <ulf.hermann@qt.io> +Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org> +(cherry picked from commit a4fa74d3e7581cb5c6bb82223ee17257f66fa41d) +--- + src/quickwidgets/qaccessiblequickwidget.cpp | 2 +- + ...ssiblequickwidget.h => qaccessiblequickwidget_p.h} | 11 +++++++++++ + src/quickwidgets/qaccessiblequickwidgetfactory.cpp | 2 +- + src/quickwidgets/quickwidgets.pro | 2 +- + 4 files changed, 14 insertions(+), 3 deletions(-) + rename src/quickwidgets/{qaccessiblequickwidget.h => qaccessiblequickwidget_p.h} (92%) + +diff --git a/src/quickwidgets/qaccessiblequickwidget.cpp b/src/quickwidgets/qaccessiblequickwidget.cpp +index 6f04d6693f..8a1c901880 100644 +--- a/src/quickwidgets/qaccessiblequickwidget.cpp ++++ b/src/quickwidgets/qaccessiblequickwidget.cpp +@@ -37,7 +37,7 @@ + ** + ****************************************************************************/ + +-#include "qaccessiblequickwidget.h" ++#include "qaccessiblequickwidget_p.h" + + #include "qquickwidget_p.h" + +diff --git a/src/quickwidgets/qaccessiblequickwidget.h b/src/quickwidgets/qaccessiblequickwidget_p.h +similarity index 92% +rename from src/quickwidgets/qaccessiblequickwidget.h +rename to src/quickwidgets/qaccessiblequickwidget_p.h +index 1f52c78c46..7c2ab930e0 100644 +--- a/src/quickwidgets/qaccessiblequickwidget.h ++++ b/src/quickwidgets/qaccessiblequickwidget_p.h +@@ -40,6 +40,17 @@ + #ifndef QACCESSIBLEQUICKWIDGET_H + #define QACCESSIBLEQUICKWIDGET_H + ++// ++// W A R N I N G ++// ------------- ++// ++// This file is not part of the Qt API. It exists purely as an ++// implementation detail. This header file may change from version to ++// version without notice, or even be removed. ++// ++// We mean it. ++// ++ + #include "qquickwidget.h" + #include <QtWidgets/qaccessiblewidget.h> + +diff --git a/src/quickwidgets/qaccessiblequickwidgetfactory.cpp b/src/quickwidgets/qaccessiblequickwidgetfactory.cpp +index 3756d0c27c..7ba88a1769 100644 +--- a/src/quickwidgets/qaccessiblequickwidgetfactory.cpp ++++ b/src/quickwidgets/qaccessiblequickwidgetfactory.cpp +@@ -38,7 +38,7 @@ + ****************************************************************************/ + + #include "qaccessiblequickwidgetfactory_p.h" +-#include "qaccessiblequickwidget.h" ++#include "qaccessiblequickwidget_p.h" + + QT_BEGIN_NAMESPACE + +diff --git a/src/quickwidgets/quickwidgets.pro b/src/quickwidgets/quickwidgets.pro +index f46deb54ac..85d156b8a3 100644 +--- a/src/quickwidgets/quickwidgets.pro ++++ b/src/quickwidgets/quickwidgets.pro +@@ -8,7 +8,7 @@ HEADERS += \ + qquickwidget.h \ + qquickwidget_p.h \ + qtquickwidgetsglobal.h \ +- qaccessiblequickwidget.h \ ++ qaccessiblequickwidget_p.h \ + qaccessiblequickwidgetfactory_p.h + + SOURCES += \ +-- +2.49.0 + +From b1fbbbcb6b0168946170a450ca01b09169b89e66 Mon Sep 17 00:00:00 2001 +From: Jaeyoon Jung <jaeyoon.jung@lge.com> +Date: Fri, 19 Feb 2021 08:11:57 +0900 +Subject: [PATCH 13/21] QQmlImportDatabase: Make sure the newly added import + path be first + +If it already exists in the import list, move it to the first place. +This is as per the description of QQmlEngine::addImportPath: +| The newly added path will be first in the importPathList(). + +Change-Id: I782d355c46ada2a46cff72e63326208f39028e01 +Reviewed-by: Ulf Hermann <ulf.hermann@qt.io> +(cherry picked from commit 3e413803c698d21f398daf0450c8f501204eb167) +--- + src/qml/qml/qqmlimport.cpp | 9 ++++++--- + tests/auto/qml/qqmlimport/tst_qqmlimport.cpp | 5 +++++ + 2 files changed, 11 insertions(+), 3 deletions(-) + +diff --git a/src/qml/qml/qqmlimport.cpp b/src/qml/qml/qqmlimport.cpp +index e7263d1850..289f11d006 100644 +--- a/src/qml/qml/qqmlimport.cpp ++++ b/src/qml/qml/qqmlimport.cpp +@@ -2119,9 +2119,12 @@ void QQmlImportDatabase::addImportPath(const QString& path) + cPath.replace(Backslash, Slash); + } + +- if (!cPath.isEmpty() +- && !fileImportPath.contains(cPath)) +- fileImportPath.prepend(cPath); ++ if (!cPath.isEmpty()) { ++ if (fileImportPath.contains(cPath)) ++ fileImportPath.move(fileImportPath.indexOf(cPath), 0); ++ else ++ fileImportPath.prepend(cPath); ++ } + } + + /*! +diff --git a/tests/auto/qml/qqmlimport/tst_qqmlimport.cpp b/tests/auto/qml/qqmlimport/tst_qqmlimport.cpp +index 9c865b3f73..1f788f7a7f 100644 +--- a/tests/auto/qml/qqmlimport/tst_qqmlimport.cpp ++++ b/tests/auto/qml/qqmlimport/tst_qqmlimport.cpp +@@ -154,6 +154,11 @@ void tst_QQmlImport::importPathOrder() + engine.addImportPath(QT_QMLTEST_DATADIR); + expectedImportPaths.prepend(QT_QMLTEST_DATADIR); + QCOMPARE(expectedImportPaths, engine.importPathList()); + -+void tst_QQuickItem::activeFocusOnTab_infiniteLoopControls() ++ // Add qml2Imports again to make it the first of the list ++ engine.addImportPath(qml2Imports); ++ expectedImportPaths.move(expectedImportPaths.indexOf(qml2Imports), 0); ++ QCOMPARE(expectedImportPaths, engine.importPathList()); + } + + Q_DECLARE_METATYPE(QQmlImports::ImportVersion) +-- +2.49.0 + +From cfae55e0beaf6636233f55940c50f82d1d5a4b96 Mon Sep 17 00:00:00 2001 +From: Ulf Hermann <ulf.hermann@qt.io> +Date: Wed, 29 Mar 2023 16:36:03 +0200 +Subject: [PATCH 14/21] Models: Avoid crashes when deleting cache items + +Pick-to: 6.5 6.2 5.15 +Fixes: QTBUG-91425 +Change-Id: I58cf9ee29922f83fc6621f771b80ed557b31f106 +Reviewed-by: Shawn Rutledge <shawn.rutledge@qt.io> +Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io> +(cherry picked from commit 0cfdecba54e4f40468c4c9a8a6668cc1bc0eff65) + +* asturmlechner 2023-04-08: Resolve conflict with dev branch commit + c2d490a2385ea6f389340a296acaac0fa198c8b9 (qAsConst to std::as_const) +--- + .../qml/qqmldelegatemodel/tst_qqmldelegatemodel.cpp | 12 ++++++++++++ + 1 file changed, 12 insertions(+) + +diff --git a/tests/auto/qml/qqmldelegatemodel/tst_qqmldelegatemodel.cpp b/tests/auto/qml/qqmldelegatemodel/tst_qqmldelegatemodel.cpp +index e128d77c52..e5daf2d28b 100644 +--- a/tests/auto/qml/qqmldelegatemodel/tst_qqmldelegatemodel.cpp ++++ b/tests/auto/qml/qqmldelegatemodel/tst_qqmldelegatemodel.cpp +@@ -51,6 +51,7 @@ private slots: + void contextAccessedByHandler(); + void deleteRace(); + void redrawUponColumnChange(); ++ void deleteRace(); + }; + + class AbstractItemModel : public QAbstractItemModel +@@ -214,6 +215,17 @@ void tst_QQmlDelegateModel::redrawUponColumnChange() + QCOMPARE(item->property("text").toString(), "Coconut"); + } + ++void tst_QQmlDelegateModel::deleteRace() +{ -+ auto source = testFileUrl("activeFocusOnTab_infiniteLoop3.qml"); -+ QScopedPointer<QQuickView>window(new QQuickView()); -+ window->setSource(source); -+ window->show(); -+ QVERIFY(window->errors().isEmpty()); -+ QTest::keyClick(window.get(), Qt::Key_Tab); // should not hang ++ QQmlEngine engine; ++ QQmlComponent c(&engine, testFileUrl("deleteRace.qml")); ++ QVERIFY2(c.isReady(), qPrintable(c.errorString())); ++ QScopedPointer<QObject> o(c.create()); ++ QVERIFY(!o.isNull()); ++ QTRY_COMPARE(o->property("count").toInt(), 2); ++ QTRY_COMPARE(o->property("count").toInt(), 0); +} + - void tst_QQuickItem::nextItemInFocusChain() - { - if (!qt_tab_all_widgets()) + QTEST_MAIN(tst_QQmlDelegateModel) + + #include "tst_qqmldelegatemodel.moc" -- -2.36.0 +2.49.0 + +From f13592522e51087059442c254d22b582c7baa776 Mon Sep 17 00:00:00 2001 +From: Maximilian Goldstein <max.goldstein@qt.io> +Date: Wed, 9 Jun 2021 15:02:45 +0200 +Subject: [PATCH 15/21] qv4function: Fix crash due to reference being + invalidated -From 415cb49010e1f28405a6eeac16f3eb5a461330e5 Mon Sep 17 00:00:00 2001 -From: Marc Mutz <marc.mutz@kdab.com> -Date: Tue, 16 Jul 2019 11:23:37 +0200 -Subject: [PATCH 18/19] QSGOpenGLDistanceFieldGlyphCache: fix multiplication - result truncation +Function::updateInternalClass creates a reference to a QStringList that is appended to before being used. +This is unsafe and can leads to a segfault if the append() causes a reallocation. + +Fixes: QTBUG-94360 +Pick-to: 5.15 6.1 6.2 +Change-Id: Iac49e8d816cf440ca2b70e133c88314eb8df6b91 +Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io> +Reviewed-by: Andrei Golubev <andrei.golubev@qt.io> +(cherry picked from commit 7fa28f98824a94396106eadfc028b329985a0cfc) +--- + src/qml/jsruntime/qv4function.cpp | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) -The type of the expression int * int is int, so truncation has already -happened when the result is assigned to a qint64. +diff --git a/src/qml/jsruntime/qv4function.cpp b/src/qml/jsruntime/qv4function.cpp +index cf8a53cf9f..223e64271e 100644 +--- a/src/qml/jsruntime/qv4function.cpp ++++ b/src/qml/jsruntime/qv4function.cpp +@@ -136,7 +136,7 @@ void Function::updateInternalClass(ExecutionEngine *engine, const QList<QByteArr + if (duplicate == -1) { + parameterNames.append(QString::fromUtf8(param)); + } else { +- const QString &dup = parameterNames[duplicate]; ++ const QString dup = parameterNames[duplicate]; + parameterNames.append(dup); + parameterNames[duplicate] = + QString(0xfffe) + QString::number(duplicate) + dup; +-- +2.49.0 -Fix by casting one of the multiplicants to qint64 before performing -the multiplication. This multiplication cannot overflow, because int -is 32-bit on all supported platforms. +From 0672c6e9a9b41ac26f434dbdc36967051fb601b2 Mon Sep 17 00:00:00 2001 +From: Fabian Kosmale <fabian.kosmale@qt.io> +Date: Tue, 29 Mar 2022 10:44:04 +0200 +Subject: [PATCH 16/21] Quick Animations: Fix crash -The addition of 'size' to the pointer will still truncate the result, -on 32bit platforms, but that check is in itself UB. A follow-up commit -will fix the check, and with it the last truncation to 32bit. +SwipeDelegate causes the running animation job to be deleted when +calling swipe.close in swipe.completed. Employ the RETURN_IF_DELETED +check in more places to avoid crashes. -Coverity-Id: 218769 +Fixes: QTBUG-100560 +Task-number: QTBUG-103223 Pick-to: 6.3 6.2 5.15 -Change-Id: I0d71950695b9743db8c96d825e68bb1e9c47de02 -Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io> -Reviewed-by: Thiago Macieira <thiago.macieira@intel.com> -(cherry picked from commit cacfc1dbb9719c0ef55cff69dad0921ce1405438) +Change-Id: I276eeaa9aed1bdb36449b322a24641fa02c4d5e4 +Reviewed-by: Ulf Hermann <ulf.hermann@qt.io> +(cherry picked from commit 0238af0bd48b831d72126f2228d5913eccf67bae) + +* asturmlechner 2023-04-09: Resolve conflict with dev branch commit + 4938984f9a779192264757a06e6ca555fc8f5e91 --- - src/quick/scenegraph/qsgrhidistancefieldglyphcache.cpp | 2 +- + .../swipedelegate/CloseOnCompletedWorks.qml | 74 +++++++++++++++++++ + 1 file changed, 74 insertions(+) + create mode 100644 tests/manual/quickcontrols2/swipedelegate/CloseOnCompletedWorks.qml + +diff --git a/tests/manual/quickcontrols2/swipedelegate/CloseOnCompletedWorks.qml b/tests/manual/quickcontrols2/swipedelegate/CloseOnCompletedWorks.qml +new file mode 100644 +index 0000000000..38dfde41c3 +--- /dev/null ++++ b/tests/manual/quickcontrols2/swipedelegate/CloseOnCompletedWorks.qml +@@ -0,0 +1,74 @@ ++/**************************************************************************** ++** ++** Copyright (C) 2022 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:BSD$ ++** 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. ++** ++** BSD License Usage ++** Alternatively, you may use this file under the terms of the BSD license ++** as follows: ++** ++** "Redistribution and use in source and binary forms, with or without ++** modification, are permitted provided that the following conditions are ++** met: ++** * Redistributions of source code must retain the above copyright ++** notice, this list of conditions and the following disclaimer. ++** * Redistributions in binary form must reproduce the above copyright ++** notice, this list of conditions and the following disclaimer in ++** the documentation and/or other materials provided with the ++** distribution. ++** * Neither the name of The Qt Company Ltd nor the names of its ++** contributors may be used to endorse or promote products derived ++** from this software without specific prior written permission. ++** ++** ++** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ++** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ++** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ++** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ++** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ++** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ++** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ++** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ++** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ++** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ++** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." ++** ++** $QT_END_LICENSE$ ++** ++****************************************************************************/ ++ ++import QtQuick 2 ++import QtQuick.Controls 2 ++ApplicationWindow { ++ visible: true ++ width: 640 ++ height: 480 ++ ++ ListView { ++ anchors.fill: parent ++ model: 2 ++ ++ delegate: SwipeDelegate { ++ text: "Swipe me left (should not crash)" ++ ++ swipe.right: Label { ++ text: "Release (should not crash)" ++ } ++ ++ swipe.onCompleted: { ++ swipe.close() ++ } ++ } ++ } ++} +-- +2.49.0 + +From 3329a68014f64332636ac96e2c352e99d2caaadd Mon Sep 17 00:00:00 2001 +From: Joni Poikelin <joni.poikelin@qt.io> +Date: Thu, 3 Sep 2020 14:22:26 +0300 +Subject: [PATCH 17/21] Prevent crash when destroying asynchronous Loader + +Fixes: QTBUG-86255 +Pick-to: 5.15 +Change-Id: I30488b64d910a1409a43e2e98ee7ab084aec33d2 +Reviewed-by: Ulf Hermann <ulf.hermann@qt.io> +(cherry picked from commit 149c1dd07b54ee0c027d94a49d52160dc4f4e2ac) + +* asturmlechner 2023-01-06: Resolve conflict with dev branch commits + d51c007ecc8aa6256cb95cf3992e5ac34a70fa3f and + b2a4a61e8cb0839ba293783ac03c72f35c7b1307 +--- + src/qml/qml/qqmlvmemetaobject.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) -diff --git a/src/quick/scenegraph/qsgrhidistancefieldglyphcache.cpp b/src/quick/scenegraph/qsgrhidistancefieldglyphcache.cpp -index 53b6fe117f..f7cb8bede3 100644 ---- a/src/quick/scenegraph/qsgrhidistancefieldglyphcache.cpp -+++ b/src/quick/scenegraph/qsgrhidistancefieldglyphcache.cpp -@@ -512,7 +512,7 @@ bool QSGRhiDistanceFieldGlyphCache::loadPregeneratedCache(const QRawFont &font) - - int width = texInfo->allocatedArea.width(); - int height = texInfo->allocatedArea.height(); -- qint64 size = width * height; -+ qint64 size = qint64(width) * height; - if (reinterpret_cast<const char *>(textureData + size) > qtdfTableEnd) { - qWarning("qtdf table too small in font '%s'.", - qPrintable(font.familyName())); +diff --git a/src/qml/qml/qqmlvmemetaobject.cpp b/src/qml/qml/qqmlvmemetaobject.cpp +index 4fd2092fd3..0d59d197dc 100644 +--- a/src/qml/qml/qqmlvmemetaobject.cpp ++++ b/src/qml/qml/qqmlvmemetaobject.cpp +@@ -254,7 +254,7 @@ void QQmlVMEMetaObjectEndpoint::tryConnect() + if (!pd) + return; + +- if (pd->notifyIndex() != -1) ++ if (pd->notifyIndex() != -1 && ctxt->engine) + connect(target, pd->notifyIndex(), ctxt->engine); + } + -- -2.36.0 +2.49.0 + +From abdead2f5daef5aabe72882cb8005495dd93855b Mon Sep 17 00:00:00 2001 +From: Volker Hilsheimer <volker.hilsheimer@qt.io> +Date: Fri, 18 Nov 2022 14:20:20 +0100 +Subject: [PATCH 18/21] QQuickItem: Fix effective visibility for items without + parent + +Items are visible if they are children of a visible parent, and not +explicitly hidden. The effectiveVisible member stores the state and is +updated when conditions that impact the item visibility changes. + +The old code returned true for items outside a visual hierarchy, which +broke signal emission when items were removed from a parent, e.g. +because the parent got destroyed. With this change, items removed from +a visual hierarchy will emit the visibleChanged signal. + +Note: QQuickItem initializes the effectiveVisible member to true, even +if the item was created without parent item. Visual items are required +to be added to a visual hierarchy via setParentItem. For this reason, +newly created items never emit visibleChanged when they are added to +a parent. + +Adjust the QQuickItem::visible test - it creates an item hierarchy +without window. Such items are never visible, so add a window and +parent the test item hierarchy to the window's content item. + +This fixes the expected failures in the tests. It does introduce an +incompatibility with QGraphicsView and QGraphicsItem, which continue +to return true from QGraphicsItem::isVisible for items that are not +in an item hierarchy. + +[ChangeLog][Qt Quick][QQuickItem] The visible property of Items without +a parent now always returns false, and the visibleChanged signal gets +emitted when the parent item of a visible item becomes null. + +Fixes: QTBUG-108213 +Change-Id: If4b2947cefd1407853f0f29e6c3fdbd49fc9af65 +Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io> +Reviewed-by: Shawn Rutledge <shawn.rutledge@qt.io> +(cherry picked from commit d1b9a4cacfb966cf0a37983d8f8044f3aedf5de3) -From 2454c808bfe99b50084aea59adb917e805c27afa Mon Sep 17 00:00:00 2001 -From: Marc Mutz <marc.mutz@kdab.com> -Date: Tue, 16 Jul 2019 11:31:01 +0200 -Subject: [PATCH 19/19] QSGOpenGLDistanceFieldGlyphCache: fix UB (ordering of - pointers not from the same array) +CCBUG: 467909 +CCBUG: 396359 +--- + src/quick/items/qquickitem.cpp | 6 ++---- + tests/auto/quick/qquickitem/tst_qquickitem.cpp | 2 ++ + 2 files changed, 4 insertions(+), 4 deletions(-) -The code performed out of bounds checks by adding the size of the -buffer to a pointer and comparing the result to the the -one-past-the-end pointer of the buffer. +diff --git a/src/quick/items/qquickitem.cpp b/src/quick/items/qquickitem.cpp +index 8b139cb539..a5e91b2b61 100644 +--- a/src/quick/items/qquickitem.cpp ++++ b/src/quick/items/qquickitem.cpp +@@ -6082,10 +6082,8 @@ void QQuickItem::setEnabled(bool e) + + bool QQuickItemPrivate::calcEffectiveVisible() const + { +- // XXX todo - Should the effective visible of an element with no parent just be the current +- // effective visible? This would prevent pointless re-processing in the case of an element +- // moving to/from a no-parent situation, but it is different from what graphics view does. +- return explicitVisible && (!parentItem || QQuickItemPrivate::get(parentItem)->effectiveVisible); ++ // An item is visible if it is a child of a visible parent, and not explicitly hidden. ++ return explicitVisible && parentItem && QQuickItemPrivate::get(parentItem)->effectiveVisible; + } + + bool QQuickItemPrivate::setEffectiveVisibleRecur(bool newEffectiveVisible) +diff --git a/tests/auto/quick/qquickitem/tst_qquickitem.cpp b/tests/auto/quick/qquickitem/tst_qquickitem.cpp +index 42348d8dd1..34eefd85e6 100644 +--- a/tests/auto/quick/qquickitem/tst_qquickitem.cpp ++++ b/tests/auto/quick/qquickitem/tst_qquickitem.cpp +@@ -989,7 +989,9 @@ void tst_qquickitem::setParentItem() + + void tst_qquickitem::visible() + { ++ QQuickWindow window; + QQuickItem *root = new QQuickItem; ++ root->setParentItem(window.contentItem()); + + QQuickItem *child1 = new QQuickItem; + child1->setParentItem(root); +-- +2.49.0 -This is UB, for three reasons: +From 584e70bc485eb3aff7fe845c441efce24e410820 Mon Sep 17 00:00:00 2001 +From: Fushan Wen <qydwhotmail@gmail.com> +Date: Fri, 21 Apr 2023 23:38:04 +0800 +Subject: [PATCH 19/21] Revert "QQuickItem: Fix effective visibility for items + without parent" -- in one case, a qint64 is added to a pointer, silently truncating the - result on 32bit platforms +This breaks applications that use QQmlPropertyList to store QQuickItem +and don't set a parentItem for them. -- if the buffer overflow is large, the pointer value may wrap around, - yielding a result that is numerically less than the end pointer, but - still out-of-bounds. +Ref: https://github.com/musescore/MuseScore/issues/17276 -- pointer order is only defined within a C array, plus one past the - end. On failure, pointers outside that range are compared. +This reverts commit 45c22a0221937682f4496801a495458a00f76d3a. +--- + src/quick/items/qquickitem.cpp | 6 ++++-- + tests/auto/quick/qquickitem/tst_qquickitem.cpp | 2 -- + 2 files changed, 4 insertions(+), 4 deletions(-) -Fix by comparing distance(it, end) with the required size for the -chunk to be written instead. +diff --git a/src/quick/items/qquickitem.cpp b/src/quick/items/qquickitem.cpp +index a5e91b2b61..8b139cb539 100644 +--- a/src/quick/items/qquickitem.cpp ++++ b/src/quick/items/qquickitem.cpp +@@ -6082,8 +6082,10 @@ void QQuickItem::setEnabled(bool e) + + bool QQuickItemPrivate::calcEffectiveVisible() const + { +- // An item is visible if it is a child of a visible parent, and not explicitly hidden. +- return explicitVisible && parentItem && QQuickItemPrivate::get(parentItem)->effectiveVisible; ++ // XXX todo - Should the effective visible of an element with no parent just be the current ++ // effective visible? This would prevent pointless re-processing in the case of an element ++ // moving to/from a no-parent situation, but it is different from what graphics view does. ++ return explicitVisible && (!parentItem || QQuickItemPrivate::get(parentItem)->effectiveVisible); + } + + bool QQuickItemPrivate::setEffectiveVisibleRecur(bool newEffectiveVisible) +diff --git a/tests/auto/quick/qquickitem/tst_qquickitem.cpp b/tests/auto/quick/qquickitem/tst_qquickitem.cpp +index 34eefd85e6..42348d8dd1 100644 +--- a/tests/auto/quick/qquickitem/tst_qquickitem.cpp ++++ b/tests/auto/quick/qquickitem/tst_qquickitem.cpp +@@ -989,9 +989,7 @@ void tst_qquickitem::setParentItem() + + void tst_qquickitem::visible() + { +- QQuickWindow window; + QQuickItem *root = new QQuickItem; +- root->setParentItem(window.contentItem()); + + QQuickItem *child1 = new QQuickItem; + child1->setParentItem(root); +-- +2.49.0 -Pick-to: 6.3 6.2 5.15 -Change-Id: I356bb8c8a65a93b8b1c1eb7bac381dd64bea719e +From ca6a197c9589c2c9a90f7a02fd7644c9b2f3eb00 Mon Sep 17 00:00:00 2001 +From: Ulf Hermann <ulf.hermann@qt.io> +Date: Wed, 8 Feb 2023 12:14:21 +0100 +Subject: [PATCH 20/21] QML: Fortify qmlExecuteDeferred some more + +I don't know how to trigger this, but a recent crash report from the CI +shows that we can get there without a valid engine. + +Pick-to: 6.5 +Change-Id: I9f17894da82b8e7eab88181c96dfa8eaf7795523 Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io> -Reviewed-by: Thiago Macieira <thiago.macieira@intel.com> -(cherry picked from commit 8d9bd6b381bfc759d575954801b683354ad6a790) +(cherry picked from commit f69b6f0940b178b46ecbaa5f0b4956ac44e8379e) --- - src/quick/scenegraph/qsgrhidistancefieldglyphcache.cpp | 6 +++--- - 1 file changed, 3 insertions(+), 3 deletions(-) - -diff --git a/src/quick/scenegraph/qsgrhidistancefieldglyphcache.cpp b/src/quick/scenegraph/qsgrhidistancefieldglyphcache.cpp -index f7cb8bede3..219cdd5966 100644 ---- a/src/quick/scenegraph/qsgrhidistancefieldglyphcache.cpp -+++ b/src/quick/scenegraph/qsgrhidistancefieldglyphcache.cpp -@@ -446,7 +446,7 @@ bool QSGRhiDistanceFieldGlyphCache::loadPregeneratedCache(const QRawFont &font) - - const char *textureRecord = allocatorData; - for (int i = 0; i < textureCount; ++i, textureRecord += Qtdf::TextureRecordSize) { -- if (textureRecord + Qtdf::TextureRecordSize > qtdfTableEnd) { -+ if (qtdfTableEnd - textureRecord < Qtdf::TextureRecordSize) { - qWarning("qtdf table too small in font '%s'.", - qPrintable(font.familyName())); - return false; -@@ -462,7 +462,7 @@ bool QSGRhiDistanceFieldGlyphCache::loadPregeneratedCache(const QRawFont &font) - - const char *glyphRecord = textureRecord; - for (quint32 i = 0; i < glyphCount; ++i, glyphRecord += Qtdf::GlyphRecordSize) { -- if (glyphRecord + Qtdf::GlyphRecordSize > qtdfTableEnd) { -+ if (qtdfTableEnd - glyphRecord < Qtdf:: GlyphRecordSize) { - qWarning("qtdf table too small in font '%s'.", - qPrintable(font.familyName())); - return false; -@@ -513,7 +513,7 @@ bool QSGRhiDistanceFieldGlyphCache::loadPregeneratedCache(const QRawFont &font) - int width = texInfo->allocatedArea.width(); - int height = texInfo->allocatedArea.height(); - qint64 size = qint64(width) * height; -- if (reinterpret_cast<const char *>(textureData + size) > qtdfTableEnd) { -+ if (qtdfTableEnd - reinterpret_cast<const char *>(textureData) < size) { - qWarning("qtdf table too small in font '%s'.", - qPrintable(font.familyName())); - return false; + src/qml/qml/qqmlengine.cpp | 21 +++++++++++++-------- + 1 file changed, 13 insertions(+), 8 deletions(-) + +diff --git a/src/qml/qml/qqmlengine.cpp b/src/qml/qml/qqmlengine.cpp +index 4337a7f454..5ae937e22f 100644 +--- a/src/qml/qml/qqmlengine.cpp ++++ b/src/qml/qml/qqmlengine.cpp +@@ -1583,17 +1583,22 @@ void qmlExecuteDeferred(QObject *object) + { + QQmlData *data = QQmlData::get(object); + +- if (data && !data->deferredData.isEmpty() && !data->wasDeleted(object)) { +- QQmlEnginePrivate *ep = QQmlEnginePrivate::get(data->context->engine); ++ if (!data ++ || !data->context ++ || !data->context->engine ++ || data->deferredData.isEmpty() ++ || data->wasDeleted(object)) { ++ return; ++ } + +- QQmlComponentPrivate::DeferredState state; +- QQmlComponentPrivate::beginDeferred(ep, object, &state); ++ QQmlEnginePrivate *ep = QQmlEnginePrivate::get(data->context->engine); ++ QQmlComponentPrivate::DeferredState state; ++ QQmlComponentPrivate::beginDeferred(ep, object, &state); + +- // Release the reference for the deferral action (we still have one from construction) +- data->releaseDeferredData(); ++ // Release the reference for the deferral action (we still have one from construction) ++ data->releaseDeferredData(); + +- QQmlComponentPrivate::completeDeferred(ep, &state); +- } ++ QQmlComponentPrivate::completeDeferred(ep, &state); + } + + QQmlContext *qmlContext(const QObject *obj) +-- +2.49.0 + +From 11ea94fc8ea95d0ba95745a021a1b139283b8b36 Mon Sep 17 00:00:00 2001 +From: Ulf Hermann <ulf.hermann@qt.io> +Date: Mon, 10 Jul 2023 07:43:28 +0200 +Subject: [PATCH 21/21] QtQml: Clean up QQmlData ctor +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Initialize the "dummy" member even though we never use it. Static +analyzers complain about it and we may appreciate it having a defined +value in the future. Also, initialize other members inline where +possible. + +Coverity-Id: 415867 +Change-Id: Ie428eb3294d6363afe9d7ab2d2bed6e52df0b304 +Reviewed-by: Olivier De Cannière <olivier.decanniere@qt.io> +Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io> +(cherry picked from commit 10985a568db8cfb4140140967f7d247627ec4350) + +* asturmlechner 2023-08-12: Resolve conflicts with dev branch commits + 10985a568db8cfb4140140967f7d247627ec4350 and + e5246cafffb93f69a49c133210390c253fcb71f2 and + d3b3fef5a878d7fd53de6a9f9fff196a273930e3 +--- + src/qml/qml/qqmldata_p.h | 20 ++++++++++---------- + src/qml/qml/qqmlengine.cpp | 7 ++----- + 2 files changed, 12 insertions(+), 15 deletions(-) + +diff --git a/src/qml/qml/qqmldata_p.h b/src/qml/qml/qqmldata_p.h +index c44fb8608e..69dac27c9a 100644 +--- a/src/qml/qml/qqmldata_p.h ++++ b/src/qml/qml/qqmldata_p.h +@@ -185,7 +185,7 @@ public: + private: + void layout(QQmlNotifierEndpoint*); + }; +- QAtomicPointer<NotifyList> notifyList; ++ QAtomicPointer<NotifyList> notifyList = nullptr; + + inline QQmlNotifierEndpoint *notify(int index) const; + void addNotify(int index, QQmlNotifierEndpoint *); +@@ -201,12 +201,12 @@ public: + QQmlContextData *outerContext = nullptr; + QQmlContextDataRef ownContext; + +- QQmlAbstractBinding *bindings; +- QQmlBoundSignal *signalHandlers; ++ QQmlAbstractBinding *bindings = nullptr; ++ QQmlBoundSignal *signalHandlers = nullptr; + + // Linked list for QQmlContext::contextObjects +- QQmlData *nextContextObject; +- QQmlData**prevContextObject; ++ QQmlData *nextContextObject = nullptr; ++ QQmlData**prevContextObject = nullptr; + + inline bool hasBindingBit(int) const; + inline void setBindingBit(QObject *obj, int); +@@ -216,10 +216,10 @@ public: + inline void setPendingBindingBit(QObject *obj, int); + inline void clearPendingBindingBit(int); + +- quint16 lineNumber; +- quint16 columnNumber; ++ quint16 lineNumber = 0; ++ quint16 columnNumber = 0; + +- quint32 jsEngineId; // id of the engine that created the jsWrapper ++ quint32 jsEngineId = 0; // id of the engine that created the jsWrapper + + struct DeferredData { + DeferredData(); +@@ -240,7 +240,7 @@ public: + + QQmlPropertyCache *propertyCache; + +- QQmlGuardImpl *guards; ++ QQmlGuardImpl *guards = 0; + + static QQmlData *get(const QObject *object, bool create = false) { + QObjectPrivate *priv = QObjectPrivate::get(const_cast<QObject *>(object)); +@@ -289,7 +289,7 @@ public: + + private: + // For attachedProperties +- mutable QQmlDataExtended *extendedData; ++ mutable QQmlDataExtended *extendedData = nullptr; + + Q_NEVER_INLINE static QQmlData *createQQmlData(QObjectPrivate *priv); + Q_NEVER_INLINE static QQmlPropertyCache *createPropertyCache(QJSEngine *engine, QObject *object); +diff --git a/src/qml/qml/qqmlengine.cpp b/src/qml/qml/qqmlengine.cpp +index 5ae937e22f..afb117d36e 100644 +--- a/src/qml/qml/qqmlengine.cpp ++++ b/src/qml/qml/qqmlengine.cpp +@@ -719,11 +719,8 @@ void QQmlPrivate::qdeclarativeelement_destructor(QObject *o) + QQmlData::QQmlData() + : ownedByQml1(false), ownMemory(true), indestructible(true), explicitIndestructibleSet(false), + hasTaintedV4Object(false), isQueuedForDeletion(false), rootObjectInCreation(false), +- hasInterceptorMetaObject(false), hasVMEMetaObject(false), parentFrozen(false), +- bindingBitsArraySize(InlineBindingArraySize), notifyList(nullptr), +- bindings(nullptr), signalHandlers(nullptr), nextContextObject(nullptr), prevContextObject(nullptr), +- lineNumber(0), columnNumber(0), jsEngineId(0), +- propertyCache(nullptr), guards(nullptr), extendedData(nullptr) ++ hasInterceptorMetaObject(false), hasVMEMetaObject(false), parentFrozen(false), dummy(0), ++ bindingBitsArraySize(InlineBindingArraySize), propertyCache(nullptr) + { + memset(bindingBitsValue, 0, sizeof(bindingBitsValue)); + init(); -- -2.36.0 +2.49.0 |