Sync with Fedora

Resolves: bz#2025420
This commit is contained in:
Jan Grulich 2021-12-09 13:42:48 +01:00
parent 31a769d449
commit b34aebe568
11 changed files with 1375 additions and 4 deletions

View File

@ -0,0 +1,43 @@
From 92225b72b9ca6b1efc9bc7bb0c12dd7487e900a7 Mon Sep 17 00:00:00 2001
From: Dmitry Shachnev <mitya57@gmail.com>
Date: Wed, 18 Aug 2021 22:50:29 +0300
Subject: [PATCH 30/36] 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.31.1

View File

@ -0,0 +1,112 @@
From 1c33a9d045897ce755a818ebff7ddecae97885d3 Mon Sep 17 00:00:00 2001
From: Aleix Pol <aleixpol@kde.org>
Date: Tue, 21 Sep 2021 00:10:26 +0200
Subject: [PATCH 31/36] 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 8cd63a4236..a6f7009946 100644
--- a/src/quick/items/qquickloader.cpp
+++ b/src/quick/items/qquickloader.cpp
@@ -738,6 +738,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 f4b682f3f4..fe2d71b037 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>)
@@ -1491,6 +1492,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.31.1

View File

@ -0,0 +1,196 @@
From e0271324f05fee2c8670a73d1e7e89aef51532a3 Mon Sep 17 00:00:00 2001
From: Aleix Pol <aleixpol@kde.org>
Date: Thu, 23 Sep 2021 03:43:04 +0200
Subject: [PATCH 32/36] 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
QConcatenateTablesProxyModel). In those cases we would render glitchy
items until the elements are marked as dirty.
Change-Id: I615c9cacbb1b6f9dee3898b03476605e5ac39d0a
Reviewed-by: Ulf Hermann <ulf.hermann@qt.io>
(cherry picked from commit ec9251efb918f37971aeefa1f687d137d037ff12)
Reviewed-by: Qt Cherry-pick Bot <cherrypick_bot@qt-project.org>
Signed-off-by: Aleix Pol <aleixpol@kde.org>
---
src/qmlmodels/qqmldelegatemodel.cpp | 44 +++++++++++++++++++
src/qmlmodels/qqmldelegatemodel_p.h | 3 ++
.../data/redrawUponColumnChange.qml | 11 +++++
.../qqmldelegatemodel/qqmldelegatemodel.pro | 2 +-
.../tst_qqmldelegatemodel.cpp | 29 ++++++++++++
5 files changed, 88 insertions(+), 1 deletion(-)
create mode 100644 tests/auto/qml/qqmldelegatemodel/data/redrawUponColumnChange.qml
diff --git a/src/qmlmodels/qqmldelegatemodel.cpp b/src/qmlmodels/qqmldelegatemodel.cpp
index 12c3d11937..8ce3da1cf1 100644
--- a/src/qmlmodels/qqmldelegatemodel.cpp
+++ b/src/qmlmodels/qqmldelegatemodel.cpp
@@ -389,6 +389,12 @@ void QQmlDelegateModelPrivate::connectToAbstractItemModel()
q, QQmlDelegateModel, SLOT(_q_rowsRemoved(QModelIndex,int,int)));
qmlobject_connect(aim, QAbstractItemModel, SIGNAL(rowsAboutToBeRemoved(QModelIndex,int,int)),
q, QQmlDelegateModel, SLOT(_q_rowsAboutToBeRemoved(QModelIndex,int,int)));
+ qmlobject_connect(aim, QAbstractItemModel, SIGNAL(columnsInserted(QModelIndex,int,int)),
+ q, QQmlDelegateModel, SLOT(_q_columnsInserted(QModelIndex,int,int)));
+ qmlobject_connect(aim, QAbstractItemModel, SIGNAL(columnsRemoved(QModelIndex,int,int)),
+ q, QQmlDelegateModel, SLOT(_q_columnsRemoved(QModelIndex,int,int)));
+ qmlobject_connect(aim, QAbstractItemModel, SIGNAL(columnsMoved(QModelIndex,int,int,QModelIndex,int)),
+ q, QQmlDelegateModel, SLOT(_q_columnsMoved(QModelIndex,int,int,QModelIndex,int)));
qmlobject_connect(aim, QAbstractItemModel, SIGNAL(dataChanged(QModelIndex,QModelIndex,QVector<int>)),
q, QQmlDelegateModel, SLOT(_q_dataChanged(QModelIndex,QModelIndex,QVector<int>)));
qmlobject_connect(aim, QAbstractItemModel, SIGNAL(rowsMoved(QModelIndex,int,int,QModelIndex,int)),
@@ -413,6 +419,12 @@ void QQmlDelegateModelPrivate::disconnectFromAbstractItemModel()
q, SLOT(_q_rowsAboutToBeRemoved(QModelIndex,int,int)));
QObject::disconnect(aim, SIGNAL(rowsRemoved(QModelIndex,int,int)),
q, SLOT(_q_rowsRemoved(QModelIndex,int,int)));
+ QObject::disconnect(aim, SIGNAL(columnsInserted(QModelIndex,int,int)), q,
+ SLOT(_q_columnsInserted(QModelIndex,int,int)));
+ QObject::disconnect(aim, SIGNAL(columnsRemoved(QModelIndex,int,int)), q,
+ SLOT(_q_columnsRemoved(QModelIndex,int,int)));
+ QObject::disconnect(aim, SIGNAL(columnsMoved(QModelIndex,int,int,QModelIndex,int)), q,
+ SLOT(_q_columnsMoved(QModelIndex,int,int,QModelIndex,int)));
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)),
@@ -1953,6 +1965,38 @@ void QQmlDelegateModel::_q_rowsMoved(
}
}
+void QQmlDelegateModel::_q_columnsInserted(const QModelIndex &parent, int begin, int end)
+{
+ Q_D(QQmlDelegateModel);
+ Q_UNUSED(end);
+ if (parent == d->m_adaptorModel.rootIndex && begin == 0) {
+ // mark all items as changed
+ _q_itemsChanged(0, d->m_count, QVector<int>());
+ }
+}
+
+void QQmlDelegateModel::_q_columnsRemoved(const QModelIndex &parent, int begin, int end)
+{
+ Q_D(QQmlDelegateModel);
+ Q_UNUSED(end);
+ if (parent == d->m_adaptorModel.rootIndex && begin == 0) {
+ // mark all items as changed
+ _q_itemsChanged(0, d->m_count, QVector<int>());
+ }
+}
+
+void QQmlDelegateModel::_q_columnsMoved(const QModelIndex &parent, int start, int end,
+ const QModelIndex &destination, int column)
+{
+ Q_D(QQmlDelegateModel);
+ Q_UNUSED(end);
+ if ((parent == d->m_adaptorModel.rootIndex && start == 0)
+ || (destination == d->m_adaptorModel.rootIndex && column == 0)) {
+ // mark all items as changed
+ _q_itemsChanged(0, d->m_count, QVector<int>());
+ }
+}
+
void QQmlDelegateModel::_q_dataChanged(const QModelIndex &begin, const QModelIndex &end, const QVector<int> &roles)
{
Q_D(QQmlDelegateModel);
diff --git a/src/qmlmodels/qqmldelegatemodel_p.h b/src/qmlmodels/qqmldelegatemodel_p.h
index 8aab4badca..d140bfbaaf 100644
--- a/src/qmlmodels/qqmldelegatemodel_p.h
+++ b/src/qmlmodels/qqmldelegatemodel_p.h
@@ -152,6 +152,9 @@ private Q_SLOTS:
void _q_itemsMoved(int from, int to, int count);
void _q_modelReset();
void _q_rowsInserted(const QModelIndex &,int,int);
+ void _q_columnsInserted(const QModelIndex &, int, int);
+ void _q_columnsRemoved(const QModelIndex &, int, int);
+ void _q_columnsMoved(const QModelIndex &, int, int, const QModelIndex &, int);
void _q_rowsAboutToBeRemoved(const QModelIndex &parent, int begin, int end);
void _q_rowsRemoved(const QModelIndex &,int,int);
void _q_rowsMoved(const QModelIndex &, int, int, const QModelIndex &, int);
diff --git a/tests/auto/qml/qqmldelegatemodel/data/redrawUponColumnChange.qml b/tests/auto/qml/qqmldelegatemodel/data/redrawUponColumnChange.qml
new file mode 100644
index 0000000000..206133bb39
--- /dev/null
+++ b/tests/auto/qml/qqmldelegatemodel/data/redrawUponColumnChange.qml
@@ -0,0 +1,11 @@
+import QtQuick 2.8
+
+ListView {
+ id: root
+ width: 200
+ height: 200
+
+ delegate: Text {
+ text: display
+ }
+}
diff --git a/tests/auto/qml/qqmldelegatemodel/qqmldelegatemodel.pro b/tests/auto/qml/qqmldelegatemodel/qqmldelegatemodel.pro
index 7fdd3ab5f1..fbd72f6a44 100644
--- a/tests/auto/qml/qqmldelegatemodel/qqmldelegatemodel.pro
+++ b/tests/auto/qml/qqmldelegatemodel/qqmldelegatemodel.pro
@@ -2,7 +2,7 @@ CONFIG += testcase
TARGET = tst_qqmldelegatemodel
macos:CONFIG -= app_bundle
-QT += qml testlib core-private qml-private qmlmodels-private
+QT += qml quick testlib core-private qml-private qmlmodels-private
SOURCES += tst_qqmldelegatemodel.cpp
diff --git a/tests/auto/qml/qqmldelegatemodel/tst_qqmldelegatemodel.cpp b/tests/auto/qml/qqmldelegatemodel/tst_qqmldelegatemodel.cpp
index 87f42c0c8a..1d338ac330 100644
--- a/tests/auto/qml/qqmldelegatemodel/tst_qqmldelegatemodel.cpp
+++ b/tests/auto/qml/qqmldelegatemodel/tst_qqmldelegatemodel.cpp
@@ -27,8 +27,12 @@
****************************************************************************/
#include <QtTest/qtest.h>
+#include <QtCore/QConcatenateTablesProxyModel>
+#include <QtGui/QStandardItemModel>
#include <QtQml/qqmlcomponent.h>
#include <QtQmlModels/private/qqmldelegatemodel_p.h>
+#include <QtQuick/qquickview.h>
+#include <QtQuick/qquickitem.h>
#include "../../shared/util.h"
@@ -42,6 +46,7 @@ public:
private slots:
void valueWithoutCallingObjectFirst_data();
void valueWithoutCallingObjectFirst();
+ void redrawUponColumnChange();
};
class AbstractItemModel : public QAbstractItemModel
@@ -134,6 +139,30 @@ void tst_QQmlDelegateModel::valueWithoutCallingObjectFirst()
QCOMPARE(model->variantValue(index, role), expectedValue);
}
+void tst_QQmlDelegateModel::redrawUponColumnChange()
+{
+ QStandardItemModel m1;
+ m1.appendRow({
+ new QStandardItem("Banana"),
+ new QStandardItem("Coconut"),
+ });
+
+ QQuickView view(testFileUrl("redrawUponColumnChange.qml"));
+ QCOMPARE(view.status(), QQuickView::Ready);
+ view.show();
+ QQuickItem *root = view.rootObject();
+ root->setProperty("model", QVariant::fromValue<QObject *>(&m1));
+
+ QObject *item = root->property("currentItem").value<QObject *>();
+ QVERIFY(item);
+ QCOMPARE(item->property("text").toString(), "Banana");
+
+ QVERIFY(root);
+ m1.removeColumn(0);
+
+ QCOMPARE(item->property("text").toString(), "Coconut");
+}
+
QTEST_MAIN(tst_QQmlDelegateModel)
#include "tst_qqmldelegatemodel.moc"
--
2.31.1

View File

@ -0,0 +1,119 @@
From 9c0030bc8e828ecfbd8a4c8dd6bbfcbd3655b71c 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 33/36] 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.31.1

View File

@ -0,0 +1,483 @@
From c1ddd97c87c729c7d05c7a74f82d41cfc5bd9cf8 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 34/36] 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.31.1

View File

@ -0,0 +1,71 @@
From 9dde7b66a30a33074fc2c2c682b53b18791dba0d 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 35/36] 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.31.1

View File

@ -0,0 +1,192 @@
From 55324650f9e759a43dce927f823c9858574106c3 Mon Sep 17 00:00:00 2001
From: Alexey Edelev <alexey.edelev@qt.io>
Date: Tue, 12 Jan 2021 16:37:09 +0100
Subject: [PATCH 36/36] Do not revert properties of deleted objects
If state contains revert action of properties of deleted objects,
we should avoid adding them to apply list
Fixes: QTBUG-85106
Pick-to: 5.15
Change-Id: Iff57eb9958a054476096f6d951ab7390277a2b39
Reviewed-by: Ulf Hermann <ulf.hermann@qt.io>
(cherry picked from commit 96763dbb105fde20431a264789ac27abfdab841c)
---
src/quick/util/qquickstate.cpp | 5 ++
.../data/revertNullObjectBinding.qml | 48 +++++++++++++
.../quick/qquickstates/tst_qquickstates.cpp | 68 +++++++++++++++++++
3 files changed, 121 insertions(+)
create mode 100644 tests/auto/quick/qquickstates/data/revertNullObjectBinding.qml
diff --git a/src/quick/util/qquickstate.cpp b/src/quick/util/qquickstate.cpp
index 71ab1f4d62..6a72754bde 100644
--- a/src/quick/util/qquickstate.cpp
+++ b/src/quick/util/qquickstate.cpp
@@ -635,6 +635,11 @@ void QQuickState::apply(QQuickTransition *trans, QQuickState *revert)
}
}
if (!found) {
+ // If revert list contains bindings assigned to deleted objects, we need to
+ // prevent reverting properties of those objects.
+ if (d->revertList.at(ii).binding() && !d->revertList.at(ii).property().object()) {
+ continue;
+ }
QVariant cur = d->revertList.at(ii).property().read();
QQmlPropertyPrivate::removeBinding(d->revertList.at(ii).property());
diff --git a/tests/auto/quick/qquickstates/data/revertNullObjectBinding.qml b/tests/auto/quick/qquickstates/data/revertNullObjectBinding.qml
new file mode 100644
index 0000000000..dee82f52ed
--- /dev/null
+++ b/tests/auto/quick/qquickstates/data/revertNullObjectBinding.qml
@@ -0,0 +1,48 @@
+import QtQuick 2.12
+import Qt.test 1.0
+
+Item {
+ id: root
+ readonly property int someProp: 1234
+
+ property bool state1Active: false
+ property bool state2Active: false
+ StateGroup {
+ states: [
+ State {
+ id: state1
+ name: "state1"
+ when: state1Active
+ changes: [
+ PropertyChanges {
+ objectName: "propertyChanges1"
+ target: ContainingObj.obj
+ prop: root.someProp
+ }
+ ]
+ }
+ ]}
+ StateGroup {
+ states: [
+ State {
+ id: state2
+ name: "state2"
+ when: state2Active
+ changes: [
+ PropertyChanges {
+ objectName: "propertyChanges2"
+ target: ContainingObj.obj
+ prop: 11111
+ }
+ ]
+ }
+ ]
+ }
+
+ Component.onCompleted: {
+ state1Active = true;
+ state2Active = true;
+
+ ContainingObj.reset()
+ }
+}
diff --git a/tests/auto/quick/qquickstates/tst_qquickstates.cpp b/tests/auto/quick/qquickstates/tst_qquickstates.cpp
index d5fea3cb28..849522454f 100644
--- a/tests/auto/quick/qquickstates/tst_qquickstates.cpp
+++ b/tests/auto/quick/qquickstates/tst_qquickstates.cpp
@@ -79,6 +79,55 @@ private:
QML_DECLARE_TYPE(MyRect)
QML_DECLARE_TYPEINFO(MyRect, QML_HAS_ATTACHED_PROPERTIES)
+class RemovableObj : public QObject
+{
+ Q_OBJECT
+ Q_PROPERTY(int prop READ prop WRITE setProp NOTIFY propChanged)
+
+public:
+ RemovableObj(QObject *parent) : QObject(parent), m_prop(4321) { }
+ int prop() const { return m_prop; }
+
+public slots:
+ void setProp(int prop)
+ {
+ if (m_prop == prop)
+ return;
+
+ m_prop = prop;
+ emit propChanged(m_prop);
+ }
+
+signals:
+ void propChanged(int prop);
+
+private:
+ int m_prop;
+};
+
+class ContainingObj : public QObject
+{
+ Q_OBJECT
+ Q_PROPERTY(RemovableObj *obj READ obj NOTIFY objChanged)
+ RemovableObj *m_obj;
+
+public:
+ ContainingObj() : m_obj(new RemovableObj(this)) { }
+ RemovableObj *obj() const { return m_obj; }
+
+ Q_INVOKABLE void reset()
+ {
+ if (m_obj) {
+ m_obj->deleteLater();
+ }
+
+ m_obj = new RemovableObj(this);
+ emit objChanged();
+ }
+signals:
+ void objChanged();
+};
+
class tst_qquickstates : public QQmlDataTest
{
Q_OBJECT
@@ -140,12 +189,20 @@ private slots:
void duplicateStateName();
void trivialWhen();
void parentChangeCorrectReversal();
+ void revertNullObjectBinding();
};
void tst_qquickstates::initTestCase()
{
QQmlDataTest::initTestCase();
qmlRegisterType<MyRect>("Qt.test", 1, 0, "MyRectangle");
+ qmlRegisterSingletonType<ContainingObj>(
+ "Qt.test", 1, 0, "ContainingObj", [](QQmlEngine *engine, QJSEngine *) {
+ static ContainingObj instance;
+ engine->setObjectOwnership(&instance, QQmlEngine::CppOwnership);
+ return &instance;
+ });
+ qmlRegisterUncreatableType<RemovableObj>("Qt.test", 1, 0, "RemovableObj", "Uncreatable");
}
QByteArray tst_qquickstates::fullDataPath(const QString &path) const
@@ -1692,6 +1749,17 @@ void tst_qquickstates::parentChangeCorrectReversal()
QCOMPARE(oldX, stayingRectX.read().toDouble());
}
+void tst_qquickstates::revertNullObjectBinding()
+{
+ QQmlEngine engine;
+
+ QQmlComponent c(&engine, testFileUrl("revertNullObjectBinding.qml"));
+ QScopedPointer<QObject> root { c.create() };
+ QVERIFY(root);
+ QTest::qWait(10);
+ QQmlProperty state2Active(root.get(), "state2Active");
+ state2Active.write(false);
+}
QTEST_MAIN(tst_qquickstates)
--
2.31.1

View File

@ -0,0 +1,58 @@
From 8e85afd011ea25eec0aa710481e2474dbaaee869 Mon Sep 17 00:00:00 2001
From: Volker Hilsheimer <volker.hilsheimer@qt.io>
Date: Wed, 17 Mar 2021 16:52:21 +0100
Subject: [PATCH 37/41] QQuickItemAnimation: close potential memory leak
Fix static analyzer warning bff6cb4333f531d5a72f7bf6dc1485f6.
If ownership of viaData is not passed to the viaAction, then the object
might be leaked. Use std::unique_ptr to make ownership transfer explicit
and implicitly delete unowned objects.
Pick-to: 6.1 5.15
Change-Id: I89f2a6b630941a98a74db302bc1ab08055c71974
Reviewed-by: Ulf Hermann <ulf.hermann@qt.io>
(cherry picked from commit 78aea267209c34abeb4895712dc76c923aa46165)
---
src/quick/items/qquickitemanimation.cpp | 11 ++++-------
1 file changed, 4 insertions(+), 7 deletions(-)
diff --git a/src/quick/items/qquickitemanimation.cpp b/src/quick/items/qquickitemanimation.cpp
index 23694e2de3..dfb56ccc00 100644
--- a/src/quick/items/qquickitemanimation.cpp
+++ b/src/quick/items/qquickitemanimation.cpp
@@ -230,8 +230,8 @@ QAbstractAnimationJob* QQuickParentAnimation::transition(QQuickStateActions &act
{
Q_D(QQuickParentAnimation);
- QQuickParentAnimationData *data = new QQuickParentAnimationData;
- QQuickParentAnimationData *viaData = new QQuickParentAnimationData;
+ std::unique_ptr<QQuickParentAnimationData> data(new QQuickParentAnimationData);
+ std::unique_ptr<QQuickParentAnimationData> viaData(new QQuickParentAnimationData);
bool hasExplicit = false;
if (d->target && d->newParent) {
@@ -377,8 +377,8 @@ QAbstractAnimationJob* QQuickParentAnimation::transition(QQuickStateActions &act
QParallelAnimationGroupJob *ag = new QParallelAnimationGroupJob;
if (d->via)
- viaAction->setAnimAction(viaData);
- targetAction->setAnimAction(data);
+ viaAction->setAnimAction(viaData.release());
+ targetAction->setAnimAction(data.release());
//take care of any child animations
bool valid = d->defaultProperty.isValid();
@@ -405,9 +405,6 @@ QAbstractAnimationJob* QQuickParentAnimation::transition(QQuickStateActions &act
topLevelGroup->appendAnimation(d->via ? viaAction : targetAction);
}
return initInstance(topLevelGroup);
- } else {
- delete data;
- delete viaData;
}
return nullptr;
}
--
2.33.1

View File

@ -0,0 +1,30 @@
From fe8c06d78a1b2f261806797c6f15f313cc3fc490 Mon Sep 17 00:00:00 2001
From: Maximilian Goldstein <max.goldstein@qt.io>
Date: Tue, 23 Feb 2021 16:10:44 +0100
Subject: [PATCH 38/41] qqmldelegatemodel: Fix out of bounds cache removal
Pick-to: 5.15 6.0 6.1
Task-number: QTBUG-91276
Change-Id: I1ddbb4a3326d61ff94e3881beb64a14dade11c46
Reviewed-by: Ulf Hermann <ulf.hermann@qt.io>
(cherry picked from commit 31ad81d81e623a34cd71567b9507f16601f1c1d4)
---
src/qmlmodels/qqmldelegatemodel.cpp | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/qmlmodels/qqmldelegatemodel.cpp b/src/qmlmodels/qqmldelegatemodel.cpp
index 8ce3da1cf1..8a74a854f4 100644
--- a/src/qmlmodels/qqmldelegatemodel.cpp
+++ b/src/qmlmodels/qqmldelegatemodel.cpp
@@ -1621,7 +1621,7 @@ void QQmlDelegateModelPrivate::itemsRemoved(
removed[i] = 0;
for (const Compositor::Remove &remove : removes) {
- for (; cacheIndex < remove.cacheIndex; ++cacheIndex)
+ for (; cacheIndex < remove.cacheIndex && cacheIndex < m_cache.size(); ++cacheIndex)
incrementIndexes(m_cache.at(cacheIndex), m_groupCount, removed);
for (int i = 1; i < m_groupCount; ++i) {
--
2.33.1

View File

@ -0,0 +1,50 @@
From d7ede3462d7e12e4fa60a6efa1b83e2157be4b00 Mon Sep 17 00:00:00 2001
From: Andreas Hartmetz <andreas@ixgreen.de>
Date: Fri, 5 Mar 2021 12:41:06 +0100
Subject: [PATCH 39/41] QQuickWindow: don't leak old screenChanged connections
Connections could accumulate. Because the newest one was invoked
last due to how signal-slot invocations are ordered, rendering
was correct, but the stale connections caused unnecessary updates
(and wasted a small amount of memory).
This comes from a misunderstanding I had at the time about how
QMetaObject::Connection works. Destroying or overwriting one does
not affect the actual connection.
While at it, also modernize the connect().
Pick-to: 5.15 6.0 6.1
Change-Id: Idde81bdbff8947ed517bf2740d623a395c0acb74
Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
Reviewed-by: Shawn Rutledge <shawn.rutledge@qt.io>
(cherry picked from commit 9f8292d48913c5bc50377749c2b3e030cf16d703)
---
src/quick/items/qquickwindow.cpp | 7 +++----
1 file changed, 3 insertions(+), 4 deletions(-)
diff --git a/src/quick/items/qquickwindow.cpp b/src/quick/items/qquickwindow.cpp
index 9ff91eb9a0..fbb807ca96 100644
--- a/src/quick/items/qquickwindow.cpp
+++ b/src/quick/items/qquickwindow.cpp
@@ -450,15 +450,14 @@ void QQuickWindow::physicalDpiChanged()
void QQuickWindow::handleScreenChanged(QScreen *screen)
{
Q_D(QQuickWindow);
+ disconnect(d->physicalDpiChangedConnection);
if (screen) {
physicalDpiChanged();
// When physical DPI changes on the same screen, either the resolution or the device pixel
// ratio changed. We must check what it is. Device pixel ratio does not have its own
// ...Changed() signal.
- d->physicalDpiChangedConnection = connect(screen, SIGNAL(physicalDotsPerInchChanged(qreal)),
- this, SLOT(physicalDpiChanged()));
- } else {
- disconnect(d->physicalDpiChangedConnection);
+ d->physicalDpiChangedConnection = connect(screen, &QScreen::physicalDotsPerInchChanged,
+ this, &QQuickWindow::physicalDpiChanged);
}
d->forcePolish();
--
2.33.1

View File

@ -10,7 +10,7 @@
Summary: Qt5 - QtDeclarative component
Name: qt5-%{qt_module}
Version: 5.15.2
Release: 9%{?dist}
Release: 10%{?dist}
# See LICENSE.GPL LICENSE.LGPL LGPL_EXCEPTION.txt, for details
License: LGPLv2 with exceptions or GPLv3 with exceptions
@ -55,9 +55,23 @@ Patch25: 0025-Give-a-warning-when-StyledText-encounters-a-non-supp.patch
Patch26: 0026-Add-missing-limits-include-to-fix-build-with-GCC-11.patch
Patch27: 0027-Document-that-StyledText-also-supports-nbsp-and-quot.patch
Patch28: 0028-Support-apos-in-styled-text.patch
Patch29: 0029-Remove-unused-QPointer-QQuickPointerMask.patch
Patch30: 0030-Include-limits-in-Yarr.h-to-fix-build-with-GCC-11.patch
Patch31: 0031-QQuickLoader-Do-not-incubate-if-the-source-arrives-a.patch
Patch32: 0032-QQmlDelegateModel-Refresh-the-view-when-a-column-is-.patch
Patch33: 0033-Fix-sweep-step-for-tainted-QObject-JavaScript-wrappe.patch
Patch34: 0034-Fix-distorted-text-with-subpixel-matrix-translation.patch
Patch35: 0035-Revert-Fix-for-possible-crash-in-QSGDefaultLayer-gra.patch
Patch36: 0036-Do-not-revert-properties-of-deleted-objects.patch
Patch37: 0037-QQuickItemAnimation-close-potential-memory-leak.patch
Patch38: 0038-qqmldelegatemodel-Fix-out-of-bounds-cache-removal.patch
Patch39: 0039-QQuickWindow-don-t-leak-old-screenChanged-connection.patch
## upstreamable patches
Patch0: %{name}-gcc11.patch
Patch100: %{name}-gcc11.patch
# https://pagure.io/fedora-kde/SIG/issue/82
Patch101: qtdeclarative-5.15.0-FixMaxXMaxYExtent.patch
# filter qml provides
%global __provides_exclude_from ^%{_qt5_archdatadir}/qml/.*\\.so$
@ -121,8 +135,7 @@ Requires: %{name}%{?_isa} = %{version}-%{release}
%endif
%prep
%setup -q -n %{qt_module}-everywhere-src-%{version}
%patch0 -p1
%autosetup -n %{qt_module}-everywhere-src-%{version} -p1
%build
@ -256,6 +269,10 @@ make check -k -C tests ||:
%endif
%changelog
* Thu Dec 09 2021 Jan Grulich <jgrulich@redhat.com> - 5.15.2-10
- Sync with Fedora
Resolves: bz#2025420
* Wed Sep 08 2021 Jan Grulich <jgrulich@redhat.com> - 5.15.2-9
- Sync with Fedora:
- sync kde/5.15 branch fixes