diff --git a/.gitignore b/.gitignore index dd65155..41e8fc9 100644 --- a/.gitignore +++ b/.gitignore @@ -12,3 +12,4 @@ /qtdeclarative-everywhere-opensource-src-5.15.5.tar.xz /qtdeclarative-everywhere-opensource-src-5.15.6.tar.xz /qtdeclarative-everywhere-opensource-src-5.15.7.tar.xz +/qtdeclarative-everywhere-opensource-src-5.15.8.tar.xz diff --git a/0001-Document-that-StyledText-also-supports-nbsp-and-quot.patch b/0001-Document-that-StyledText-also-supports-nbsp-and-quot.patch index b4b0970..ea064bc 100644 --- a/0001-Document-that-StyledText-also-supports-nbsp-and-quot.patch +++ b/0001-Document-that-StyledText-also-supports-nbsp-and-quot.patch @@ -1,7 +1,7 @@ -From 43b6267d024afd655a8c0c8c833f71850d7a8bb9 Mon Sep 17 00:00:00 2001 +From 3f272e04492cd884deb4e7948e39b749809d5256 Mon Sep 17 00:00:00 2001 From: Albert Astals Cid Date: Fri, 21 May 2021 13:17:15 +0200 -Subject: [PATCH 01/18] Document that StyledText also supports   and +Subject: [PATCH 01/21] Document that StyledText also supports   and " Change-Id: I1715f8ae8ec8d0fbaf6dbe2b8663cc169da663cd @@ -25,5 +25,5 @@ index 6230186933..c1571fc6f5 100644 \c Text.StyledText parser is strict, requiring tags to be correctly nested. -- -2.37.3 +2.39.0 diff --git a/0002-Support-apos-in-styled-text.patch b/0002-Support-apos-in-styled-text.patch index 9715951..a43df9d 100644 --- a/0002-Support-apos-in-styled-text.patch +++ b/0002-Support-apos-in-styled-text.patch @@ -1,7 +1,7 @@ -From 8e28af8076873503bbf036487aaf7310407a2f11 Mon Sep 17 00:00:00 2001 +From bf4b4f3dfb3534e7919c50faa60a0fe7fbcdacf5 Mon Sep 17 00:00:00 2001 From: Albert Astals Cid Date: Fri, 21 May 2021 13:42:35 +0200 -Subject: [PATCH 02/18] Support ' in styled text +Subject: [PATCH 02/21] Support ' in styled text Pick-to: 6.1 5.15 Change-Id: I4a8db963e52a7899ab1796f9a560e8029cc1c929 @@ -40,5 +40,5 @@ index d531fc9205..a25af90414 100644 textOut += QChar(34); else if (entity == QLatin1String("nbsp")) -- -2.37.3 +2.39.0 diff --git a/0003-Remove-unused-QPointer-QQuickPointerMask.patch b/0003-Remove-unused-QPointer-QQuickPointerMask.patch index fdb521f..a10a96a 100644 --- a/0003-Remove-unused-QPointer-QQuickPointerMask.patch +++ b/0003-Remove-unused-QPointer-QQuickPointerMask.patch @@ -1,7 +1,7 @@ -From 0f3b328766038c1161f4f613a0bf3a4fcbdb4cef Mon Sep 17 00:00:00 2001 +From da206ac99b58218a1e51a2e75032647d24cd0fdb Mon Sep 17 00:00:00 2001 From: Albert Astals Cid Date: Thu, 17 Jun 2021 16:32:28 +0200 -Subject: [PATCH 03/18] Remove unused QPointer +Subject: [PATCH 03/21] Remove unused QPointer Change-Id: I009fa6bbd8599dc3bb2e810176fe20e70ed50851 Reviewed-by: Shawn Rutledge @@ -31,5 +31,5 @@ index fba383e268..0d63618622 100644 QPointF targetStartPos; QPointF lastPos; -- -2.37.3 +2.39.0 diff --git a/0004-QQmlDelegateModel-Refresh-the-view-when-a-column-is-.patch b/0004-QQmlDelegateModel-Refresh-the-view-when-a-column-is-.patch index afdc492..3a90ba4 100644 --- a/0004-QQmlDelegateModel-Refresh-the-view-when-a-column-is-.patch +++ b/0004-QQmlDelegateModel-Refresh-the-view-when-a-column-is-.patch @@ -1,7 +1,7 @@ -From ad09b853a3a137127de847d4d6d55f73ab09899d Mon Sep 17 00:00:00 2001 +From e61200ff7222c31e73dbc779ba4a70073775cc0c Mon Sep 17 00:00:00 2001 From: Aleix Pol Date: Thu, 23 Sep 2021 03:43:04 +0200 -Subject: [PATCH 04/18] QQmlDelegateModel: Refresh the view when a column is +Subject: [PATCH 04/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 @@ -174,5 +174,5 @@ index 35f1e2c94d..1722447830 100644 #include "tst_qqmldelegatemodel.moc" -- -2.37.3 +2.39.0 diff --git a/0005-Fix-sweep-step-for-tainted-QObject-JavaScript-wrappe.patch b/0005-Fix-sweep-step-for-tainted-QObject-JavaScript-wrappe.patch index 7242c29..cfd0400 100644 --- a/0005-Fix-sweep-step-for-tainted-QObject-JavaScript-wrappe.patch +++ b/0005-Fix-sweep-step-for-tainted-QObject-JavaScript-wrappe.patch @@ -1,7 +1,7 @@ -From 55caf921033dc1f310c1d370a046908cb0a6bc57 Mon Sep 17 00:00:00 2001 +From ab781c9f5364ddfab0bfe9626a9dd01bd6bc046e Mon Sep 17 00:00:00 2001 From: Vlad Zahorodnii Date: Sun, 10 Oct 2021 21:04:21 +0300 -Subject: [PATCH 05/18] Fix sweep step for tainted QObject JavaScript wrappers +Subject: [PATCH 05/21] Fix sweep step for tainted QObject JavaScript wrappers Currently, whenever the garbage collector runs, it will destroy all valid tainted wrappers. @@ -115,5 +115,5 @@ index 5d635aa63b..824fd89e5b 100644 // engine2 doesn't own the object as engine1 was the first to wrap it above. // Therefore, no effect here. -- -2.37.3 +2.39.0 diff --git a/0006-Fix-TapHandler-so-that-it-actually-registers-a-tap.patch b/0006-Fix-TapHandler-so-that-it-actually-registers-a-tap.patch new file mode 100644 index 0000000..c49f6d2 --- /dev/null +++ b/0006-Fix-TapHandler-so-that-it-actually-registers-a-tap.patch @@ -0,0 +1,73 @@ +From b8f474a4dd5fa58edfba73e565499bcdad679291 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Jan=20Arve=20S=C3=A6ther?= +Date: Thu, 3 Sep 2020 10:51:01 +0200 +Subject: [PATCH 06/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. + +In QtGui, QSinglePointEvent will construct itself with a point id of 0 +if there is a valid point, and with a point id of -1 if the point is +invalid (the default constructor does the latter). +However, QQuickSinglePointHandler::wantsPointerEvent() did not agree +with that, because it assumed that a point id of 0 meant +uninitialized/invalid point. +The fix is to change QQuickSinglePointHandler::wantsPointerEvent() and +QQuickHandlerPoint so that it assumes that the id -1 is now an invalid +point, (instead of 0) + +Change-Id: I8c9683dfe06ebb77c5342a26f08174b67e7cbd90 +Reviewed-by: Shawn Rutledge +(cherry picked from commit 8d3a91016506fd0afedb0be535f7c34a4ca762f6) +--- + src/quick/handlers/qquickhandlerpoint.cpp | 4 ++-- + src/quick/handlers/qquicksinglepointhandler.cpp | 4 ++-- + 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 +--- a/src/quick/handlers/qquickhandlerpoint.cpp ++++ b/src/quick/handlers/qquickhandlerpoint.cpp +@@ -82,7 +82,7 @@ void QQuickHandlerPoint::localize(QQuickItem *item) + + void QQuickHandlerPoint::reset() + { +- m_id = 0; ++ m_id = -1; + m_uniqueId = QPointingDeviceUniqueId(); + m_position = QPointF(); + m_scenePosition = QPointF(); +@@ -165,7 +165,7 @@ void QQuickHandlerPoint::reset(const QVector &points) + pressureSum += point.pressure(); + ellipseDiameterSum += point.ellipseDiameters(); + } +- m_id = 0; ++ m_id = -1; + m_uniqueId = QPointingDeviceUniqueId(); + // 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 +--- a/src/quick/handlers/qquicksinglepointhandler.cpp ++++ b/src/quick/handlers/qquicksinglepointhandler.cpp +@@ -75,7 +75,7 @@ bool QQuickSinglePointHandler::wantsPointerEvent(QQuickPointerEvent *event) + if (!QQuickPointerDeviceHandler::wantsPointerEvent(event)) + return false; + +- if (d->pointInfo.id()) { ++ if (d->pointInfo.id() != -1) { + // We already know which one we want, so check whether it's there. + // It's expected to be an update or a release. + // If we no longer want it, cancel the grab. +@@ -125,7 +125,7 @@ bool QQuickSinglePointHandler::wantsPointerEvent(QQuickPointerEvent *event) + chosen->setAccepted(); + } + } +- return d->pointInfo.id(); ++ return d->pointInfo.id() != -1; + } + + void QQuickSinglePointHandler::handlePointerEventImpl(QQuickPointerEvent *event) +-- +2.39.0 + diff --git a/0006-Revert-Fix-for-possible-crash-in-QSGDefaultLayer-gra.patch b/0006-Revert-Fix-for-possible-crash-in-QSGDefaultLayer-gra.patch deleted file mode 100644 index 24de445..0000000 --- a/0006-Revert-Fix-for-possible-crash-in-QSGDefaultLayer-gra.patch +++ /dev/null @@ -1,71 +0,0 @@ -From 1cb0de43684c7f23cd121d48ebd84a9da688c8ef Mon Sep 17 00:00:00 2001 -From: Laszlo Agocs -Date: Mon, 11 Oct 2021 15:37:33 +0200 -Subject: [PATCH 06/18] 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 -(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.37.3 - diff --git a/0007-Fix-TapHandler-so-that-it-actually-registers-a-tap.patch b/0007-Fix-TapHandler-so-that-it-actually-registers-a-tap.patch deleted file mode 100644 index a22fa4c..0000000 --- a/0007-Fix-TapHandler-so-that-it-actually-registers-a-tap.patch +++ /dev/null @@ -1,73 +0,0 @@ -From 7dd0d9f9ce9bbd5e21f017069256d52b397a6195 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Jan=20Arve=20S=C3=A6ther?= -Date: Thu, 3 Sep 2020 10:51:01 +0200 -Subject: [PATCH 07/18] Fix TapHandler so that it actually registers a tap - -This bug caused all quick examples that used the -shared\LauncherList.qml to be broken. - -In QtGui, QSinglePointEvent will construct itself with a point id of 0 -if there is a valid point, and with a point id of -1 if the point is -invalid (the default constructor does the latter). -However, QQuickSinglePointHandler::wantsPointerEvent() did not agree -with that, because it assumed that a point id of 0 meant -uninitialized/invalid point. -The fix is to change QQuickSinglePointHandler::wantsPointerEvent() and -QQuickHandlerPoint so that it assumes that the id -1 is now an invalid -point, (instead of 0) - -Change-Id: I8c9683dfe06ebb77c5342a26f08174b67e7cbd90 -Reviewed-by: Shawn Rutledge -(cherry picked from commit 8d3a91016506fd0afedb0be535f7c34a4ca762f6) ---- - src/quick/handlers/qquickhandlerpoint.cpp | 4 ++-- - src/quick/handlers/qquicksinglepointhandler.cpp | 4 ++-- - 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 ---- a/src/quick/handlers/qquickhandlerpoint.cpp -+++ b/src/quick/handlers/qquickhandlerpoint.cpp -@@ -82,7 +82,7 @@ void QQuickHandlerPoint::localize(QQuickItem *item) - - void QQuickHandlerPoint::reset() - { -- m_id = 0; -+ m_id = -1; - m_uniqueId = QPointingDeviceUniqueId(); - m_position = QPointF(); - m_scenePosition = QPointF(); -@@ -165,7 +165,7 @@ void QQuickHandlerPoint::reset(const QVector &points) - pressureSum += point.pressure(); - ellipseDiameterSum += point.ellipseDiameters(); - } -- m_id = 0; -+ m_id = -1; - m_uniqueId = QPointingDeviceUniqueId(); - // 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 ---- a/src/quick/handlers/qquicksinglepointhandler.cpp -+++ b/src/quick/handlers/qquicksinglepointhandler.cpp -@@ -75,7 +75,7 @@ bool QQuickSinglePointHandler::wantsPointerEvent(QQuickPointerEvent *event) - if (!QQuickPointerDeviceHandler::wantsPointerEvent(event)) - return false; - -- if (d->pointInfo.id()) { -+ if (d->pointInfo.id() != -1) { - // We already know which one we want, so check whether it's there. - // It's expected to be an update or a release. - // If we no longer want it, cancel the grab. -@@ -125,7 +125,7 @@ bool QQuickSinglePointHandler::wantsPointerEvent(QQuickPointerEvent *event) - chosen->setAccepted(); - } - } -- return d->pointInfo.id(); -+ return d->pointInfo.id() != -1; - } - - void QQuickSinglePointHandler::handlePointerEventImpl(QQuickPointerEvent *event) --- -2.37.3 - diff --git a/0007-Revert-Fix-TapHandler-so-that-it-actually-registers-.patch b/0007-Revert-Fix-TapHandler-so-that-it-actually-registers-.patch new file mode 100644 index 0000000..413e137 --- /dev/null +++ b/0007-Revert-Fix-TapHandler-so-that-it-actually-registers-.patch @@ -0,0 +1,61 @@ +From de04cfb654a09fe7d0f8454b8a8de9243284e1d2 Mon Sep 17 00:00:00 2001 +From: Albert Astals Cid +Date: Tue, 16 Nov 2021 22:43:37 +0100 +Subject: [PATCH 07/21] Revert "Fix TapHandler so that it actually registers a + tap" + +This reverts commit 36e8ccd434f948e4f11a8f9d59139ec072e41ff5. + +It's causing regresions +--- + src/quick/handlers/qquickhandlerpoint.cpp | 4 ++-- + src/quick/handlers/qquicksinglepointhandler.cpp | 4 ++-- + 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 +--- a/src/quick/handlers/qquickhandlerpoint.cpp ++++ b/src/quick/handlers/qquickhandlerpoint.cpp +@@ -82,7 +82,7 @@ void QQuickHandlerPoint::localize(QQuickItem *item) + + void QQuickHandlerPoint::reset() + { +- m_id = -1; ++ m_id = 0; + m_uniqueId = QPointingDeviceUniqueId(); + m_position = QPointF(); + m_scenePosition = QPointF(); +@@ -165,7 +165,7 @@ void QQuickHandlerPoint::reset(const QVector &points) + pressureSum += point.pressure(); + ellipseDiameterSum += point.ellipseDiameters(); + } +- m_id = -1; ++ m_id = 0; + m_uniqueId = QPointingDeviceUniqueId(); + // 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 +--- a/src/quick/handlers/qquicksinglepointhandler.cpp ++++ b/src/quick/handlers/qquicksinglepointhandler.cpp +@@ -75,7 +75,7 @@ bool QQuickSinglePointHandler::wantsPointerEvent(QQuickPointerEvent *event) + if (!QQuickPointerDeviceHandler::wantsPointerEvent(event)) + return false; + +- if (d->pointInfo.id() != -1) { ++ if (d->pointInfo.id()) { + // We already know which one we want, so check whether it's there. + // It's expected to be an update or a release. + // If we no longer want it, cancel the grab. +@@ -125,7 +125,7 @@ bool QQuickSinglePointHandler::wantsPointerEvent(QQuickPointerEvent *event) + chosen->setAccepted(); + } + } +- return d->pointInfo.id() != -1; ++ return d->pointInfo.id(); + } + + void QQuickSinglePointHandler::handlePointerEventImpl(QQuickPointerEvent *event) +-- +2.39.0 + diff --git a/0008-QQmlJs-FixedPoolArray-fix-UB-precondition-violation-.patch b/0008-QQmlJs-FixedPoolArray-fix-UB-precondition-violation-.patch new file mode 100644 index 0000000..568f207 --- /dev/null +++ b/0008-QQmlJs-FixedPoolArray-fix-UB-precondition-violation-.patch @@ -0,0 +1,36 @@ +From 99ada3c3d329b6d7136b0425841dcaa654c9c05b Mon Sep 17 00:00:00 2001 +From: Marc Mutz +Date: Tue, 21 Dec 2021 09:20:17 +0100 +Subject: [PATCH 08/21] 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 +(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::isComplex) { + for (int i = 0; i < count; ++i) + new (data + i) T(vector.at(i)); +- } else { ++ } else if (count) { + memcpy(data, static_cast(vector.constData()), count * sizeof(T)); + } + } +-- +2.39.0 + diff --git a/0008-Revert-Fix-TapHandler-so-that-it-actually-registers-.patch b/0008-Revert-Fix-TapHandler-so-that-it-actually-registers-.patch deleted file mode 100644 index b7b7d58..0000000 --- a/0008-Revert-Fix-TapHandler-so-that-it-actually-registers-.patch +++ /dev/null @@ -1,61 +0,0 @@ -From ad102f786a12d0cc139bfbebea8edbab3dd8206d Mon Sep 17 00:00:00 2001 -From: Albert Astals Cid -Date: Tue, 16 Nov 2021 22:43:37 +0100 -Subject: [PATCH 08/18] Revert "Fix TapHandler so that it actually registers a - tap" - -This reverts commit 36e8ccd434f948e4f11a8f9d59139ec072e41ff5. - -It's causing regresions ---- - src/quick/handlers/qquickhandlerpoint.cpp | 4 ++-- - src/quick/handlers/qquicksinglepointhandler.cpp | 4 ++-- - 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 ---- a/src/quick/handlers/qquickhandlerpoint.cpp -+++ b/src/quick/handlers/qquickhandlerpoint.cpp -@@ -82,7 +82,7 @@ void QQuickHandlerPoint::localize(QQuickItem *item) - - void QQuickHandlerPoint::reset() - { -- m_id = -1; -+ m_id = 0; - m_uniqueId = QPointingDeviceUniqueId(); - m_position = QPointF(); - m_scenePosition = QPointF(); -@@ -165,7 +165,7 @@ void QQuickHandlerPoint::reset(const QVector &points) - pressureSum += point.pressure(); - ellipseDiameterSum += point.ellipseDiameters(); - } -- m_id = -1; -+ m_id = 0; - m_uniqueId = QPointingDeviceUniqueId(); - // 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 ---- a/src/quick/handlers/qquicksinglepointhandler.cpp -+++ b/src/quick/handlers/qquicksinglepointhandler.cpp -@@ -75,7 +75,7 @@ bool QQuickSinglePointHandler::wantsPointerEvent(QQuickPointerEvent *event) - if (!QQuickPointerDeviceHandler::wantsPointerEvent(event)) - return false; - -- if (d->pointInfo.id() != -1) { -+ if (d->pointInfo.id()) { - // We already know which one we want, so check whether it's there. - // It's expected to be an update or a release. - // If we no longer want it, cancel the grab. -@@ -125,7 +125,7 @@ bool QQuickSinglePointHandler::wantsPointerEvent(QQuickPointerEvent *event) - chosen->setAccepted(); - } - } -- return d->pointInfo.id() != -1; -+ return d->pointInfo.id(); - } - - void QQuickSinglePointHandler::handlePointerEventImpl(QQuickPointerEvent *event) --- -2.37.3 - diff --git a/0009-QQmlJs-FixedPoolArray-fix-UB-precondition-violation-.patch b/0009-QQmlJs-FixedPoolArray-fix-UB-precondition-violation-.patch deleted file mode 100644 index fde8f4b..0000000 --- a/0009-QQmlJs-FixedPoolArray-fix-UB-precondition-violation-.patch +++ /dev/null @@ -1,36 +0,0 @@ -From 2d11778ce9348716ce936ce11c89ced58d8ec188 Mon Sep 17 00:00:00 2001 -From: Marc Mutz -Date: Tue, 21 Dec 2021 09:20:17 +0100 -Subject: [PATCH 09/18] 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 -(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::isComplex) { - for (int i = 0; i < count; ++i) - new (data + i) T(vector.at(i)); -- } else { -+ } else if (count) { - memcpy(data, static_cast(vector.constData()), count * sizeof(T)); - } - } --- -2.37.3 - diff --git a/0009-V4-Do-not-call-dtor-of-an-object-we-continue-to-use.patch b/0009-V4-Do-not-call-dtor-of-an-object-we-continue-to-use.patch new file mode 100644 index 0000000..e87e423 --- /dev/null +++ b/0009-V4-Do-not-call-dtor-of-an-object-we-continue-to-use.patch @@ -0,0 +1,51 @@ +From b964ba12bf118afbbf42cd9e4e7b4903ad107060 Mon Sep 17 00:00:00 2001 +From: Ulf Hermann +Date: Thu, 3 Feb 2022 10:02:06 +0100 +Subject: [PATCH 09/21] 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(). + +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 +Reviewed-by: Qt CI Bot +Reviewed-by: Fabian Kosmale +(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 e57cdd8278..94613598af 100644 +--- a/src/qml/jsruntime/qv4qobjectwrapper.cpp ++++ b/src/qml/jsruntime/qv4qobjectwrapper.cpp +@@ -1145,8 +1145,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); +@@ -1176,7 +1175,7 @@ void QObjectWrapper::destroyObject(bool lastCall) + } + } + +- h->~Data(); ++ h->destroy(); + } + + +-- +2.39.0 + diff --git a/0010-Make-sure-QQuickWidget-and-its-offscreen-window-s-sc.patch b/0010-Make-sure-QQuickWidget-and-its-offscreen-window-s-sc.patch new file mode 100644 index 0000000..1b2fb96 --- /dev/null +++ b/0010-Make-sure-QQuickWidget-and-its-offscreen-window-s-sc.patch @@ -0,0 +1,84 @@ +From d8808a609a81660e9de9abc6b1b71ea01f0d6f40 Mon Sep 17 00:00:00 2001 +From: Vlad Zahorodnii +Date: Sat, 29 Jan 2022 21:59:33 +0200 +Subject: [PATCH 10/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. +However, if the parent widget argument is passed to the QQuickWidget's +constructor, then QQuickWidget's and the offscreen window's screens can +be different and that can create rendering issues, e.g. blurry text if +the primary screen and QQuickWidget's screen have different scale +factors. + +Change-Id: I10c62b5635664f943b11828773f14017f198a770 +Reviewed-by: David Edmundson +Reviewed-by: Laszlo Agocs +(cherry picked from commit a2a2734bffa1459639b31fb3f4f83873ba44ab5c) +--- + src/quickwidgets/qquickwidget.cpp | 26 +++++++++++--------------- + 1 file changed, 11 insertions(+), 15 deletions(-) + +diff --git a/src/quickwidgets/qquickwidget.cpp b/src/quickwidgets/qquickwidget.cpp +index 39780f8de3..223d91f579 100644 +--- a/src/quickwidgets/qquickwidget.cpp ++++ b/src/quickwidgets/qquickwidget.cpp +@@ -106,6 +106,7 @@ void QQuickWidgetPrivate::init(QQmlEngine* e) + + renderControl = new QQuickWidgetRenderControl(q); + offscreenWindow = new QQuickWindow(*new QQuickOffcreenWindowPrivate(),renderControl); ++ offscreenWindow->setScreen(q->screen()); + offscreenWindow->setTitle(QString::fromLatin1("Offscreen")); + offscreenWindow->setObjectName(QString::fromLatin1("QQuickOffScreenWindow")); + // Do not call create() on offscreenWindow. +@@ -901,9 +902,7 @@ void QQuickWidgetPrivate::createContext() + + context = new QOpenGLContext; + context->setFormat(offscreenWindow->requestedFormat()); +- const QWindow *win = q->window()->windowHandle(); +- if (win && win->screen()) +- context->setScreen(win->screen()); ++ context->setScreen(q->screen()); + QOpenGLContext *shareContext = qt_gl_global_share_context(); + if (!shareContext) + shareContext = QWidgetPrivate::get(q->window())->shareContext(); +@@ -1520,19 +1519,16 @@ bool QQuickWidget::event(QEvent *e) + d->handleWindowChange(); + break; + +- case QEvent::ScreenChangeInternal: +- if (QWindow *window = this->window()->windowHandle()) { +- QScreen *newScreen = window->screen(); +- +- if (d->offscreenWindow) +- d->offscreenWindow->setScreen(newScreen); +- if (d->offscreenSurface) +- d->offscreenSurface->setScreen(newScreen); ++ case QEvent::ScreenChangeInternal: { ++ QScreen *newScreen = screen(); ++ if (d->offscreenWindow) ++ d->offscreenWindow->setScreen(newScreen); ++ if (d->offscreenSurface) ++ d->offscreenSurface->setScreen(newScreen); + #if QT_CONFIG(opengl) +- if (d->context) +- d->context->setScreen(newScreen); ++ if (d->context) ++ d->context->setScreen(newScreen); + #endif +- } + + if (d->useSoftwareRenderer + #if QT_CONFIG(opengl) +@@ -1545,7 +1541,7 @@ bool QQuickWidget::event(QEvent *e) + d->render(true); + } + break; +- ++ } + case QEvent::Show: + case QEvent::Move: + d->updatePosition(); +-- +2.39.0 + diff --git a/0010-V4-Do-not-call-dtor-of-an-object-we-continue-to-use.patch b/0010-V4-Do-not-call-dtor-of-an-object-we-continue-to-use.patch deleted file mode 100644 index a3c1aa3..0000000 --- a/0010-V4-Do-not-call-dtor-of-an-object-we-continue-to-use.patch +++ /dev/null @@ -1,51 +0,0 @@ -From eb04ee7e02c5e7a2b84b129c09f13025242688d6 Mon Sep 17 00:00:00 2001 -From: Ulf Hermann -Date: Thu, 3 Feb 2022 10:02:06 +0100 -Subject: [PATCH 10/18] 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(). - -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 -Reviewed-by: Qt CI Bot -Reviewed-by: Fabian Kosmale -(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.37.3 - diff --git a/0011-Make-sure-QQuickWidget-and-its-offscreen-window-s-sc.patch b/0011-Make-sure-QQuickWidget-and-its-offscreen-window-s-sc.patch deleted file mode 100644 index bedaf01..0000000 --- a/0011-Make-sure-QQuickWidget-and-its-offscreen-window-s-sc.patch +++ /dev/null @@ -1,84 +0,0 @@ -From 436f3c0550f64b4cb629480a6b7ceb1381f30501 Mon Sep 17 00:00:00 2001 -From: Vlad Zahorodnii -Date: Sat, 29 Jan 2022 21:59:33 +0200 -Subject: [PATCH 11/18] Make sure QQuickWidget and its offscreen window's - screens are always in sync - -By default, the offscreen window is placed on the primary screen. -However, if the parent widget argument is passed to the QQuickWidget's -constructor, then QQuickWidget's and the offscreen window's screens can -be different and that can create rendering issues, e.g. blurry text if -the primary screen and QQuickWidget's screen have different scale -factors. - -Change-Id: I10c62b5635664f943b11828773f14017f198a770 -Reviewed-by: David Edmundson -Reviewed-by: Laszlo Agocs -(cherry picked from commit a2a2734bffa1459639b31fb3f4f83873ba44ab5c) ---- - src/quickwidgets/qquickwidget.cpp | 26 +++++++++++--------------- - 1 file changed, 11 insertions(+), 15 deletions(-) - -diff --git a/src/quickwidgets/qquickwidget.cpp b/src/quickwidgets/qquickwidget.cpp -index 39780f8de3..223d91f579 100644 ---- a/src/quickwidgets/qquickwidget.cpp -+++ b/src/quickwidgets/qquickwidget.cpp -@@ -106,6 +106,7 @@ void QQuickWidgetPrivate::init(QQmlEngine* e) - - renderControl = new QQuickWidgetRenderControl(q); - offscreenWindow = new QQuickWindow(*new QQuickOffcreenWindowPrivate(),renderControl); -+ offscreenWindow->setScreen(q->screen()); - offscreenWindow->setTitle(QString::fromLatin1("Offscreen")); - offscreenWindow->setObjectName(QString::fromLatin1("QQuickOffScreenWindow")); - // Do not call create() on offscreenWindow. -@@ -901,9 +902,7 @@ void QQuickWidgetPrivate::createContext() - - context = new QOpenGLContext; - context->setFormat(offscreenWindow->requestedFormat()); -- const QWindow *win = q->window()->windowHandle(); -- if (win && win->screen()) -- context->setScreen(win->screen()); -+ context->setScreen(q->screen()); - QOpenGLContext *shareContext = qt_gl_global_share_context(); - if (!shareContext) - shareContext = QWidgetPrivate::get(q->window())->shareContext(); -@@ -1520,19 +1519,16 @@ bool QQuickWidget::event(QEvent *e) - d->handleWindowChange(); - break; - -- case QEvent::ScreenChangeInternal: -- if (QWindow *window = this->window()->windowHandle()) { -- QScreen *newScreen = window->screen(); -- -- if (d->offscreenWindow) -- d->offscreenWindow->setScreen(newScreen); -- if (d->offscreenSurface) -- d->offscreenSurface->setScreen(newScreen); -+ case QEvent::ScreenChangeInternal: { -+ QScreen *newScreen = screen(); -+ if (d->offscreenWindow) -+ d->offscreenWindow->setScreen(newScreen); -+ if (d->offscreenSurface) -+ d->offscreenSurface->setScreen(newScreen); - #if QT_CONFIG(opengl) -- if (d->context) -- d->context->setScreen(newScreen); -+ if (d->context) -+ d->context->setScreen(newScreen); - #endif -- } - - if (d->useSoftwareRenderer - #if QT_CONFIG(opengl) -@@ -1545,7 +1541,7 @@ bool QQuickWidget::event(QEvent *e) - d->render(true); - } - break; -- -+ } - case QEvent::Show: - case QEvent::Move: - d->updatePosition(); --- -2.37.3 - diff --git a/0011-QQuickItem-Guard-against-cycles-in-nextPrevItemInTab.patch b/0011-QQuickItem-Guard-against-cycles-in-nextPrevItemInTab.patch new file mode 100644 index 0000000..50b960f --- /dev/null +++ b/0011-QQuickItem-Guard-against-cycles-in-nextPrevItemInTab.patch @@ -0,0 +1,122 @@ +From 052dba54ae335b42fdcd1c0c68c9fce0031ffe9e Mon Sep 17 00:00:00 2001 +From: Fabian Kosmale +Date: Wed, 4 May 2022 09:10:54 +0200 +Subject: [PATCH 11/21] QQuickItem: Guard against cycles in + nextPrevItemInTabFocusChain +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 +Reviewed-by: Volker Hilsheimer +(cherry picked from commit e74bcf751495d9fe27efd195bc04e2a6ae6732a4) +--- + 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 + +diff --git a/src/quick/items/qquickitem.cpp b/src/quick/items/qquickitem.cpp +index 75f1457816..9de244ed9e 100644 +--- a/src/quick/items/qquickitem.cpp ++++ b/src/quick/items/qquickitem.cpp +@@ -59,6 +59,7 @@ + #include + #include + #include ++#include + + #include + #include +@@ -2526,6 +2527,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 cycleDetector; + do { + qCDebug(DBG_FOCUS) << "QQuickItemPrivate::nextPrevItemInTabFocusChain: current:" << current; + qCDebug(DBG_FOCUS) << "QQuickItemPrivate::nextPrevItemInTabFocusChain: from:" << from; +@@ -2592,7 +2594,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 ++ ++Item { ++ visible: true ++ Item { ++ visible: false ++ Item { ++ objectName: "hiddenChild" ++ activeFocusOnTab: true ++ focus: true ++ } ++ } ++} +diff --git a/tests/auto/quick/qquickitem2/tst_qquickitem.cpp b/tests/auto/quick/qquickitem2/tst_qquickitem.cpp +index c8f251dbe1..c8ef36ee68 100644 +--- a/tests/auto/quick/qquickitem2/tst_qquickitem.cpp ++++ b/tests/auto/quick/qquickitem2/tst_qquickitem.cpp +@@ -67,6 +67,7 @@ private slots: + void activeFocusOnTab10(); + void activeFocusOnTab_infiniteLoop_data(); + void activeFocusOnTab_infiniteLoop(); ++ void activeFocusOnTab_infiniteLoopControls(); + + void nextItemInFocusChain(); + void nextItemInFocusChain2(); +@@ -1057,6 +1058,17 @@ void tst_QQuickItem::activeFocusOnTab_infiniteLoop() + QCOMPARE(item, window->rootObject()); + } + ++ ++void tst_QQuickItem::activeFocusOnTab_infiniteLoopControls() ++{ ++ auto source = testFileUrl("activeFocusOnTab_infiniteLoop3.qml"); ++ QScopedPointerwindow(new QQuickView()); ++ window->setSource(source); ++ window->show(); ++ QVERIFY(window->errors().isEmpty()); ++ QTest::keyClick(window.get(), Qt::Key_Tab); // should not hang ++} ++ + void tst_QQuickItem::nextItemInFocusChain() + { + if (!qt_tab_all_widgets()) +-- +2.39.0 + diff --git a/0012-QQuickItem-Guard-against-cycles-in-nextPrevItemInTab.patch b/0012-QQuickItem-Guard-against-cycles-in-nextPrevItemInTab.patch deleted file mode 100644 index 50f9d95..0000000 --- a/0012-QQuickItem-Guard-against-cycles-in-nextPrevItemInTab.patch +++ /dev/null @@ -1,122 +0,0 @@ -From 74c8c421763597f778313ea976fffdc03183226b Mon Sep 17 00:00:00 2001 -From: Fabian Kosmale -Date: Wed, 4 May 2022 09:10:54 +0200 -Subject: [PATCH 12/18] QQuickItem: Guard against cycles in - nextPrevItemInTabFocusChain -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 -Reviewed-by: Volker Hilsheimer -(cherry picked from commit e74bcf751495d9fe27efd195bc04e2a6ae6732a4) ---- - 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 - -diff --git a/src/quick/items/qquickitem.cpp b/src/quick/items/qquickitem.cpp -index 75f1457816..9de244ed9e 100644 ---- a/src/quick/items/qquickitem.cpp -+++ b/src/quick/items/qquickitem.cpp -@@ -59,6 +59,7 @@ - #include - #include - #include -+#include - - #include - #include -@@ -2526,6 +2527,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 cycleDetector; - do { - qCDebug(DBG_FOCUS) << "QQuickItemPrivate::nextPrevItemInTabFocusChain: current:" << current; - qCDebug(DBG_FOCUS) << "QQuickItemPrivate::nextPrevItemInTabFocusChain: from:" << from; -@@ -2592,7 +2594,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 -+ -+Item { -+ visible: true -+ Item { -+ visible: false -+ Item { -+ objectName: "hiddenChild" -+ activeFocusOnTab: true -+ focus: true -+ } -+ } -+} -diff --git a/tests/auto/quick/qquickitem2/tst_qquickitem.cpp b/tests/auto/quick/qquickitem2/tst_qquickitem.cpp -index c8f251dbe1..c8ef36ee68 100644 ---- a/tests/auto/quick/qquickitem2/tst_qquickitem.cpp -+++ b/tests/auto/quick/qquickitem2/tst_qquickitem.cpp -@@ -67,6 +67,7 @@ private slots: - void activeFocusOnTab10(); - void activeFocusOnTab_infiniteLoop_data(); - void activeFocusOnTab_infiniteLoop(); -+ void activeFocusOnTab_infiniteLoopControls(); - - void nextItemInFocusChain(); - void nextItemInFocusChain2(); -@@ -1057,6 +1058,17 @@ void tst_QQuickItem::activeFocusOnTab_infiniteLoop() - QCOMPARE(item, window->rootObject()); - } - -+ -+void tst_QQuickItem::activeFocusOnTab_infiniteLoopControls() -+{ -+ auto source = testFileUrl("activeFocusOnTab_infiniteLoop3.qml"); -+ QScopedPointerwindow(new QQuickView()); -+ window->setSource(source); -+ window->show(); -+ QVERIFY(window->errors().isEmpty()); -+ QTest::keyClick(window.get(), Qt::Key_Tab); // should not hang -+} -+ - void tst_QQuickItem::nextItemInFocusChain() - { - if (!qt_tab_all_widgets()) --- -2.37.3 - diff --git a/0012-QSGOpenGLDistanceFieldGlyphCache-fix-multiplication-.patch b/0012-QSGOpenGLDistanceFieldGlyphCache-fix-multiplication-.patch new file mode 100644 index 0000000..37a1ed4 --- /dev/null +++ b/0012-QSGOpenGLDistanceFieldGlyphCache-fix-multiplication-.patch @@ -0,0 +1,43 @@ +From f9faa4cfa0dbbac12cdf79e56a02b9aa0022018c Mon Sep 17 00:00:00 2001 +From: Marc Mutz +Date: Tue, 16 Jul 2019 11:23:37 +0200 +Subject: [PATCH 12/21] QSGOpenGLDistanceFieldGlyphCache: fix multiplication + result truncation + +The type of the expression int * int is int, so truncation has already +happened when the result is assigned to a qint64. + +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. + +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. + +Coverity-Id: 218769 +Pick-to: 6.3 6.2 5.15 +Change-Id: I0d71950695b9743db8c96d825e68bb1e9c47de02 +Reviewed-by: Fabian Kosmale +Reviewed-by: Thiago Macieira +(cherry picked from commit cacfc1dbb9719c0ef55cff69dad0921ce1405438) +--- + src/quick/scenegraph/qsgrhidistancefieldglyphcache.cpp | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/src/quick/scenegraph/qsgrhidistancefieldglyphcache.cpp b/src/quick/scenegraph/qsgrhidistancefieldglyphcache.cpp +index eb4db0f85e..2c9868b335 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(textureData + size) > qtdfTableEnd) { + qWarning("qtdf table too small in font '%s'.", + qPrintable(font.familyName())); +-- +2.39.0 + diff --git a/0013-QSGOpenGLDistanceFieldGlyphCache-fix-UB-ordering-of-.patch b/0013-QSGOpenGLDistanceFieldGlyphCache-fix-UB-ordering-of-.patch new file mode 100644 index 0000000..c66c1ac --- /dev/null +++ b/0013-QSGOpenGLDistanceFieldGlyphCache-fix-UB-ordering-of-.patch @@ -0,0 +1,68 @@ +From 6d844f0250d97acdf66fd0d9cdabd26588e72333 Mon Sep 17 00:00:00 2001 +From: Marc Mutz +Date: Tue, 16 Jul 2019 11:31:01 +0200 +Subject: [PATCH 13/21] QSGOpenGLDistanceFieldGlyphCache: fix UB (ordering of + pointers not from the same array) + +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. + +This is UB, for three reasons: + +- in one case, a qint64 is added to a pointer, silently truncating the + result on 32bit platforms + +- 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. + +- pointer order is only defined within a C array, plus one past the + end. On failure, pointers outside that range are compared. + +Fix by comparing distance(it, end) with the required size for the +chunk to be written instead. + +Pick-to: 6.3 6.2 5.15 +Change-Id: I356bb8c8a65a93b8b1c1eb7bac381dd64bea719e +Reviewed-by: Fabian Kosmale +Reviewed-by: Thiago Macieira +(cherry picked from commit 8d9bd6b381bfc759d575954801b683354ad6a790) +--- + 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 2c9868b335..2325a2665b 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(textureData + size) > qtdfTableEnd) { ++ if (qtdfTableEnd - reinterpret_cast(textureData) < size) { + qWarning("qtdf table too small in font '%s'.", + qPrintable(font.familyName())); + return false; +-- +2.39.0 + diff --git a/0013-QSGOpenGLDistanceFieldGlyphCache-fix-multiplication-.patch b/0013-QSGOpenGLDistanceFieldGlyphCache-fix-multiplication-.patch deleted file mode 100644 index 241a805..0000000 --- a/0013-QSGOpenGLDistanceFieldGlyphCache-fix-multiplication-.patch +++ /dev/null @@ -1,43 +0,0 @@ -From 76113c63af23d516f488f5e6b9062ca97e062e9e Mon Sep 17 00:00:00 2001 -From: Marc Mutz -Date: Tue, 16 Jul 2019 11:23:37 +0200 -Subject: [PATCH 13/18] QSGOpenGLDistanceFieldGlyphCache: fix multiplication - result truncation - -The type of the expression int * int is int, so truncation has already -happened when the result is assigned to a qint64. - -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. - -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. - -Coverity-Id: 218769 -Pick-to: 6.3 6.2 5.15 -Change-Id: I0d71950695b9743db8c96d825e68bb1e9c47de02 -Reviewed-by: Fabian Kosmale -Reviewed-by: Thiago Macieira -(cherry picked from commit cacfc1dbb9719c0ef55cff69dad0921ce1405438) ---- - src/quick/scenegraph/qsgrhidistancefieldglyphcache.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(textureData + size) > qtdfTableEnd) { - qWarning("qtdf table too small in font '%s'.", - qPrintable(font.familyName())); --- -2.37.3 - diff --git a/0014-QSGOpenGLDistanceFieldGlyphCache-fix-UB-ordering-of-.patch b/0014-QSGOpenGLDistanceFieldGlyphCache-fix-UB-ordering-of-.patch deleted file mode 100644 index 63d6cf3..0000000 --- a/0014-QSGOpenGLDistanceFieldGlyphCache-fix-UB-ordering-of-.patch +++ /dev/null @@ -1,68 +0,0 @@ -From 985358efb1e60a8ff493da4d6ca9056f63dc9982 Mon Sep 17 00:00:00 2001 -From: Marc Mutz -Date: Tue, 16 Jul 2019 11:31:01 +0200 -Subject: [PATCH 14/18] QSGOpenGLDistanceFieldGlyphCache: fix UB (ordering of - pointers not from the same array) - -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. - -This is UB, for three reasons: - -- in one case, a qint64 is added to a pointer, silently truncating the - result on 32bit platforms - -- 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. - -- pointer order is only defined within a C array, plus one past the - end. On failure, pointers outside that range are compared. - -Fix by comparing distance(it, end) with the required size for the -chunk to be written instead. - -Pick-to: 6.3 6.2 5.15 -Change-Id: I356bb8c8a65a93b8b1c1eb7bac381dd64bea719e -Reviewed-by: Fabian Kosmale -Reviewed-by: Thiago Macieira -(cherry picked from commit 8d9bd6b381bfc759d575954801b683354ad6a790) ---- - 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(textureData + size) > qtdfTableEnd) { -+ if (qtdfTableEnd - reinterpret_cast(textureData) < size) { - qWarning("qtdf table too small in font '%s'.", - qPrintable(font.familyName())); - return false; --- -2.37.3 - diff --git a/0014-Reset-currentChanges-if-currentChanges-is-active-whe.patch b/0014-Reset-currentChanges-if-currentChanges-is-active-whe.patch new file mode 100644 index 0000000..521666e --- /dev/null +++ b/0014-Reset-currentChanges-if-currentChanges-is-active-whe.patch @@ -0,0 +1,38 @@ +From 5f183c1a7b2afbe50b4071e6a862c1a6d53de7fb Mon Sep 17 00:00:00 2001 +From: Tony Leinonen +Date: Thu, 21 Oct 2021 14:44:02 +0300 +Subject: [PATCH 14/21] Reset currentChanges if currentChanges is active when + refilling listView + +currentIndex was not getting updated because itemViewChangeSet was left +active from previous interaction. Clear the changes if they are still +active on refill. + +Task-number: QTBUG-92809 +Pick-to: 6.2 5.15 +Change-Id: I81558a5e0bfe0f880851fff85370bd5be60a5391 +Reviewed-by: Richard Moe Gustavsen +(cherry picked from commit 2d8033a4ffb9ca60adee29d375491d7ed2a82747) + +* asturmlechner 2021-11-09: Other part of 2d8033a4 is in qtquickcontrols2 + but only consists of tests. +--- + src/quick/items/qquickitemview.cpp | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/src/quick/items/qquickitemview.cpp b/src/quick/items/qquickitemview.cpp +index 010a0152e1..f8ad168a17 100644 +--- a/src/quick/items/qquickitemview.cpp ++++ b/src/quick/items/qquickitemview.cpp +@@ -1785,7 +1785,7 @@ void QQuickItemViewPrivate::refill(qreal from, qreal to) + + do { + bufferPause.stop(); +- if (currentChanges.hasPendingChanges() || bufferedChanges.hasPendingChanges()) { ++ if (currentChanges.hasPendingChanges() || bufferedChanges.hasPendingChanges() || currentChanges.active) { + currentChanges.reset(); + bufferedChanges.reset(); + releaseVisibleItems(reusableFlag); +-- +2.39.0 + diff --git a/0015-Don-t-convert-QByteArray-in-startDrag.patch b/0015-Don-t-convert-QByteArray-in-startDrag.patch new file mode 100644 index 0000000..ee0d6f4 --- /dev/null +++ b/0015-Don-t-convert-QByteArray-in-startDrag.patch @@ -0,0 +1,60 @@ +From 4884d7f5a3dbfddd865b594db51eeb4272565f76 Mon Sep 17 00:00:00 2001 +From: Fushan Wen +Date: Tue, 1 Nov 2022 22:35:24 +0800 +Subject: [PATCH 15/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 +(cherry picked from commit 062f9bf57657b54dc708015ec5fed3c89e5cc3ca) +Reviewed-by: Qt Cherry-pick Bot + + +(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.39.0 + diff --git a/0015-Fix-Flickable-wheel-velocity-calculation.patch b/0015-Fix-Flickable-wheel-velocity-calculation.patch deleted file mode 100644 index f8837b2..0000000 --- a/0015-Fix-Flickable-wheel-velocity-calculation.patch +++ /dev/null @@ -1,423 +0,0 @@ -From 8dbc2a0a112752ab85c688ba66e86e5598896aae Mon Sep 17 00:00:00 2001 -From: Shawn Rutledge -Date: Tue, 4 May 2021 10:12:39 +0200 -Subject: [PATCH 15/18] Fix Flickable wheel velocity calculation -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Angular velocity is defined as angle rotated divided by time elapsed. -But the historical problem with Flickable is that the calculation -ignored time, as if there was a maximum frequency of events and we -only needed to know the rotation angle per fixed unit of time. -With "clicky" mouse wheels perhaps it was a reasonable approximation. -With touchpads that provide pixel deltas, we've been doing the velocity -calculation the right way since a6ed830f4779e218b8e8f8d82dc4aa9b4b4528a1 -Now we divide by dt also in the wheel rotation case. - -That gives instantaneous velocity. Next question: how to do smoothing? -AxisData::velocityBuffer is basically a Kalman filter, but until now -it was used only when dragging ends and we animate the deceleration from -the velocity at that time. It seems to work well for smoothing the -velocity that comes from wheel events, too. So now we use that instead -of smoothVelocity, and it stays in control better. - -Next question: when a series of wheel events occurs, we have valid -dt for the dy / dt velocity calculation (or dx / dt horizontally), -but what about the initial flick? What if first thing the user does -is rotate a physical mouse wheel by one "click", how far should -Flickable move before it comes to rest? QStyleHints::wheelScrollLines() -tells us how far to move for one wheel event... in "lines", whatever -that is. Flickable doesn't know about its contents. But it "feels" -reasonable if we define a "line" as 24 pixels. At least the setting -will do something now: applications can adjust it, and some system -control panels can adjust it. A subclass of QQuickFlickable (such as -TableView) could even change QQFlickablePrivate::initialWheelFlickDistance -to be the actual number of pixels per "line", to scroll exactly by rows. -(But when the events occur faster, it moves further and faster, like it -always did.) - -OK so we know how far we want to move when the Flickable is at rest -and receives a QWheelEvent with angleDelta of 120. I.e. when isMoving() -is false. So I tried an experiment: set dt to 0.25. How far did it move? -77 pixels. Why? We're making it move via QQuickFlickablePrivate::flick() -which does some math and drives the timeline. The key formula is -qreal dist = v2 / (accel * 2.0) -which agrees with the testing: if the wheel turns by 120 units, -(120 / 0.25)^2 / (1500 * 2) =~ 77 -So it's possible to do the algebra to reverse-engineer what dt should be -so that we will move the right distance with a single wheel event, -despite the complexity of the animation itself. That's what is now -done. When the user rotates the wheel very slowly, it moves by discrete -amounts but with smooth animation. A little faster, and it speeds up, -somewhat like it did before, but with more control. If it has sped -up to a high speed and then the user rotates the wheel backwards, -it reverses instantly: we clear the Kalman filter and insert instantaneous -velocity (so it will go from there at the next event). - -On a touchpad, it also feels quite in-control because the velocity -is calculated properly as distance-delta / time-delta. Smoothing -it out doesn't hurt, and animating after release doesn't hurt. -It longer goes "zing" out of control when the wheel events come in too -frequently from a touchpad or a free-spinning wheel. - -None of this affects trackpads on macOS, because then the wheel events -have phases and pixel deltas, and we don't use this animation. We still -should try to get that working on as many OSes as possible, eventually. - -Clarify the meaning of the flickDeceleration property. - -[ChangeLog][QtQuick][Flickable] Flickable no longer tries to detect -whether you're using a "clicky" wheel or a touchpad, but rather does the -velocity calculation more correctly with elapsed time (dθ / dt). -A single rotation of a "clicky" wheel also moves a fixed distance, -which is now adjustable via QStyleHints::wheelScrollLines(). -Animation is restored, but should now stay in control on touchpads; -and it will once again transition the "moving" properties correctly -when scrolling ends. - -Fixes: QTBUG-56075 -Pick-to: 6.2 -Change-Id: I5166ca31c86335641cf407a922a3a970fced653d -Reviewed-by: Richard Moe Gustavsen -(cherry picked from commit a8fbd865140d4dd165723c7e3d4168514d4b1d0c) ---- - src/quick/items/qquickflickable.cpp | 95 +++++++++++++------ - src/quick/items/qquickflickable_p_p.h | 1 + - src/quick/util/qquicktimeline.cpp | 3 + - .../qquickflickable/tst_qquickflickable.cpp | 9 +- - tests/manual/touch/flicktext.qml | 30 ++++++ - 5 files changed, 107 insertions(+), 31 deletions(-) - -diff --git a/src/quick/items/qquickflickable.cpp b/src/quick/items/qquickflickable.cpp -index e12e85db64..9eea0e1487 100644 ---- a/src/quick/items/qquickflickable.cpp -+++ b/src/quick/items/qquickflickable.cpp -@@ -263,7 +263,8 @@ QQuickFlickablePrivate::QQuickFlickablePrivate() - , deceleration(QML_FLICK_DEFAULTDECELERATION) - , maxVelocity(QML_FLICK_DEFAULTMAXVELOCITY), reportedVelocitySmoothing(100) - , delayedPressEvent(nullptr), pressDelay(0), fixupDuration(400) -- , flickBoost(1.0), fixupMode(Normal), vTime(0), visibleArea(nullptr) -+ , flickBoost(1.0), initialWheelFlickDistance(qApp->styleHints()->wheelScrollLines() * 24) -+ , fixupMode(Normal), vTime(0), visibleArea(nullptr) - , flickableDirection(QQuickFlickable::AutoFlickDirection) - , boundsBehavior(QQuickFlickable::DragAndOvershootBounds) - , boundsMovement(QQuickFlickable::FollowBoundsBehavior) -@@ -531,10 +532,14 @@ void QQuickFlickablePrivate::updateBeginningEnd() - if (atBeginning != vData.atBeginning) { - vData.atBeginning = atBeginning; - atYBeginningChange = true; -+ if (!vData.moving && atBeginning) -+ vData.smoothVelocity.setValue(0); - } - if (atEnd != vData.atEnd) { - vData.atEnd = atEnd; - atYEndChange = true; -+ if (!vData.moving && atEnd) -+ vData.smoothVelocity.setValue(0); - } - - // Horizontal -@@ -547,10 +552,14 @@ void QQuickFlickablePrivate::updateBeginningEnd() - if (atBeginning != hData.atBeginning) { - hData.atBeginning = atBeginning; - atXBeginningChange = true; -+ if (!hData.moving && atBeginning) -+ hData.smoothVelocity.setValue(0); - } - if (atEnd != hData.atEnd) { - hData.atEnd = atEnd; - atXEndChange = true; -+ if (!hData.moving && atEnd) -+ hData.smoothVelocity.setValue(0); - } - - if (vData.extentsChanged) { -@@ -1489,6 +1498,7 @@ void QQuickFlickable::wheelEvent(QWheelEvent *event) - d->hData.velocity = 0; - d->timer.start(); - d->maybeBeginDrag(currentTimestamp, event->position()); -+ d->lastPosTime = -1; - break; - case Qt::NoScrollPhase: // default phase with an ordinary wheel mouse - case Qt::ScrollUpdate: -@@ -1515,20 +1525,34 @@ void QQuickFlickable::wheelEvent(QWheelEvent *event) - return; - } - -+ qreal elapsed = qreal(currentTimestamp - d->lastPosTime) / qreal(1000); -+ if (elapsed <= 0) { -+ d->lastPosTime = currentTimestamp; -+ qCDebug(lcWheel) << "insufficient elapsed time: can't calculate velocity" << elapsed; -+ return; -+ } -+ - if (event->source() == Qt::MouseEventNotSynthesized || event->pixelDelta().isNull()) { -- // physical mouse wheel, so use angleDelta -+ // no pixel delta (physical mouse wheel, or "dumb" touchpad), so use angleDelta - int xDelta = event->angleDelta().x(); - int yDelta = event->angleDelta().y(); -+ // For a single "clicky" wheel event (angleDelta +/- 120), -+ // we want flick() to end up moving a distance proportional to QStyleHints::wheelScrollLines(). -+ // The decel algo from there is -+ // qreal dist = v2 / (accel * 2.0); -+ // i.e. initialWheelFlickDistance = (120 / dt)^2 / (deceleration * 2) -+ // now solve for dt: -+ // dt = 120 / sqrt(deceleration * 2 * initialWheelFlickDistance) -+ if (!isMoving()) -+ elapsed = 120 / qSqrt(d->deceleration * 2 * d->initialWheelFlickDistance); - if (yflick() && yDelta != 0) { -- bool valid = false; -- if (yDelta > 0 && contentY() > -minYExtent()) { -- d->vData.velocity = qMax(yDelta*2 - d->vData.smoothVelocity.value(), qreal(d->maxVelocity/4)); -- valid = true; -- } else if (yDelta < 0 && contentY() < -maxYExtent()) { -- d->vData.velocity = qMin(yDelta*2 - d->vData.smoothVelocity.value(), qreal(-d->maxVelocity/4)); -- valid = true; -- } -- if (valid) { -+ qreal instVelocity = yDelta / elapsed; -+ // if the direction has changed, start over with filtering, to allow instant movement in the opposite direction -+ if ((instVelocity < 0 && d->vData.velocity > 0) || (instVelocity > 0 && d->vData.velocity < 0)) -+ d->vData.velocityBuffer.clear(); -+ d->vData.addVelocitySample(instVelocity, d->maxVelocity); -+ d->vData.updateVelocity(); -+ if ((yDelta > 0 && contentY() > -minYExtent()) || (yDelta < 0 && contentY() < -maxYExtent())) { - d->flickY(d->vData.velocity); - d->flickingStarted(false, true); - if (d->vData.flicking) { -@@ -1539,15 +1563,13 @@ void QQuickFlickable::wheelEvent(QWheelEvent *event) - } - } - if (xflick() && xDelta != 0) { -- bool valid = false; -- if (xDelta > 0 && contentX() > -minXExtent()) { -- d->hData.velocity = qMax(xDelta*2 - d->hData.smoothVelocity.value(), qreal(d->maxVelocity/4)); -- valid = true; -- } else if (xDelta < 0 && contentX() < -maxXExtent()) { -- d->hData.velocity = qMin(xDelta*2 - d->hData.smoothVelocity.value(), qreal(-d->maxVelocity/4)); -- valid = true; -- } -- if (valid) { -+ qreal instVelocity = xDelta / elapsed; -+ // if the direction has changed, start over with filtering, to allow instant movement in the opposite direction -+ if ((instVelocity < 0 && d->hData.velocity > 0) || (instVelocity > 0 && d->hData.velocity < 0)) -+ d->hData.velocityBuffer.clear(); -+ d->hData.addVelocitySample(instVelocity, d->maxVelocity); -+ d->hData.updateVelocity(); -+ if ((xDelta > 0 && contentX() > -minXExtent()) || (xDelta < 0 && contentX() < -maxXExtent())) { - d->flickX(d->hData.velocity); - d->flickingStarted(true, false); - if (d->hData.flicking) { -@@ -1562,18 +1584,13 @@ void QQuickFlickable::wheelEvent(QWheelEvent *event) - int xDelta = event->pixelDelta().x(); - int yDelta = event->pixelDelta().y(); - -- qreal elapsed = qreal(currentTimestamp - d->lastPosTime) / 1000.; -- if (elapsed <= 0) { -- d->lastPosTime = currentTimestamp; -- return; -- } - QVector2D velocity(xDelta / elapsed, yDelta / elapsed); -- d->lastPosTime = currentTimestamp; - d->accumulatedWheelPixelDelta += QVector2D(event->pixelDelta()); - d->drag(currentTimestamp, event->type(), event->position(), d->accumulatedWheelPixelDelta, - true, !d->scrollingPhase, true, velocity); - event->accept(); - } -+ d->lastPosTime = currentTimestamp; - - if (!event->isAccepted()) - QQuickItem::wheelEvent(event); -@@ -1744,6 +1761,10 @@ void QQuickFlickable::componentComplete() - setContentX(-minXExtent()); - if (!d->vData.explicitValue && d->vData.startMargin != 0.) - setContentY(-minYExtent()); -+ if (lcWheel().isDebugEnabled() || lcVel().isDebugEnabled()) { -+ d->timeline.setObjectName(QLatin1String("timeline for Flickable ") + objectName()); -+ d->velocityTimeline.setObjectName(QLatin1String("velocity timeline for Flickable ") + objectName()); -+ } - } - - void QQuickFlickable::viewportMoved(Qt::Orientations orient) -@@ -2504,9 +2525,23 @@ void QQuickFlickable::setMaximumFlickVelocity(qreal v) - - /*! - \qmlproperty real QtQuick::Flickable::flickDeceleration -- This property holds the rate at which a flick will decelerate. -- -- The default value is platform dependent. -+ This property holds the rate at which a flick will decelerate: -+ the higher the number, the faster it slows down when the user stops -+ flicking via touch, touchpad or mouse wheel. For example 0.0001 is nearly -+ "frictionless", and 10000 feels quite "sticky". -+ -+ The default value is platform dependent. Values of zero or less are not allowed. -+ -+ \note For touchpad flicking, some platforms drive Flickable directly by -+ sending QWheelEvents with QWheelEvent::phase() being \c Qt::ScrollMomentum, -+ after the user has released all fingers from the touchpad. In that case, -+ the operating system is controlling the deceleration, and this property has -+ no effect. -+ -+ \note For mouse wheel scrolling, and for gesture scrolling on touchpads -+ that do not have a momentum phase, extremely large values of -+ flickDeceleration can make Flickable very resistant to scrolling, -+ especially if \l maximumFlickVelocity is too small. - */ - qreal QQuickFlickable::flickDeceleration() const - { -@@ -2519,7 +2554,7 @@ void QQuickFlickable::setFlickDeceleration(qreal deceleration) - Q_D(QQuickFlickable); - if (deceleration == d->deceleration) - return; -- d->deceleration = deceleration; -+ d->deceleration = qMax(0.001, deceleration); - emit flickDecelerationChanged(); - } - -diff --git a/src/quick/items/qquickflickable_p_p.h b/src/quick/items/qquickflickable_p_p.h -index 414c9c33d6..6163613493 100644 ---- a/src/quick/items/qquickflickable_p_p.h -+++ b/src/quick/items/qquickflickable_p_p.h -@@ -241,6 +241,7 @@ public: - int pressDelay; - int fixupDuration; - qreal flickBoost; -+ qreal initialWheelFlickDistance; - - enum FixupMode { Normal, Immediate, ExtentChanged }; - FixupMode fixupMode; -diff --git a/src/quick/util/qquicktimeline.cpp b/src/quick/util/qquicktimeline.cpp -index 7ec7c827eb..abe6eb7261 100644 ---- a/src/quick/util/qquicktimeline.cpp -+++ b/src/quick/util/qquicktimeline.cpp -@@ -53,6 +53,8 @@ - - QT_BEGIN_NAMESPACE - -+Q_LOGGING_CATEGORY(lcTl, "qt.quick.timeline") -+ - struct Update { - Update(QQuickTimeLineValue *_g, qreal _v) - : g(_g), v(_v) {} -@@ -513,6 +515,7 @@ void QQuickTimeLine::reset(QQuickTimeLineValue &timeLineValue) - qWarning() << "QQuickTimeLine: Cannot reset a QQuickTimeLineValue owned by another timeline."; - return; - } -+ qCDebug(lcTl) << static_cast(this) << timeLineValue.value(); - remove(&timeLineValue); - timeLineValue._t = nullptr; - } -diff --git a/tests/auto/quick/qquickflickable/tst_qquickflickable.cpp b/tests/auto/quick/qquickflickable/tst_qquickflickable.cpp -index f3659290eb..9fa51da6f8 100644 ---- a/tests/auto/quick/qquickflickable/tst_qquickflickable.cpp -+++ b/tests/auto/quick/qquickflickable/tst_qquickflickable.cpp -@@ -870,6 +870,7 @@ void tst_qquickflickable::wheel() - QVERIFY(flick != nullptr); - QQuickFlickablePrivate *fp = QQuickFlickablePrivate::get(flick); - QSignalSpy moveEndSpy(flick, SIGNAL(movementEnded())); -+ quint64 timestamp = 10; - - // test a vertical flick - { -@@ -877,6 +878,7 @@ void tst_qquickflickable::wheel() - QWheelEvent event(pos, window->mapToGlobal(pos), QPoint(), QPoint(0,-120), - Qt::NoButton, Qt::NoModifier, Qt::NoScrollPhase, false); - event.setAccepted(false); -+ event.setTimestamp(timestamp); - QGuiApplication::sendEvent(window.data(), &event); - } - -@@ -887,6 +889,7 @@ void tst_qquickflickable::wheel() - QCOMPARE(fp->velocityTimeline.isActive(), false); - QCOMPARE(fp->timeline.isActive(), false); - QTest::qWait(50); // make sure that onContentYChanged won't sneak in again -+ timestamp += 50; - QCOMPARE(flick->property("movementsAfterEnd").value(), 0); // QTBUG-55886 - - // get ready to test horizontal flick -@@ -900,8 +903,8 @@ void tst_qquickflickable::wheel() - QPoint pos(200, 200); - QWheelEvent event(pos, window->mapToGlobal(pos), QPoint(), QPoint(-120,0), - Qt::NoButton, Qt::NoModifier, Qt::NoScrollPhase, false); -- - event.setAccepted(false); -+ event.setTimestamp(timestamp); - QGuiApplication::sendEvent(window.data(), &event); - } - -@@ -926,11 +929,13 @@ void tst_qquickflickable::trackpad() - QVERIFY(flick != nullptr); - QSignalSpy moveEndSpy(flick, SIGNAL(movementEnded())); - QPoint pos(200, 200); -+ quint64 timestamp = 10; - - { - QWheelEvent event(pos, window->mapToGlobal(pos), QPoint(0,-100), QPoint(0,-120), - Qt::NoButton, Qt::NoModifier, Qt::ScrollBegin, false); - event.setAccepted(false); -+ event.setTimestamp(timestamp++); - QGuiApplication::sendEvent(window.data(), &event); - } - -@@ -944,6 +949,7 @@ void tst_qquickflickable::trackpad() - QWheelEvent event(pos, window->mapToGlobal(pos), QPoint(-100,0), QPoint(-120,0), - Qt::NoButton, Qt::NoModifier, Qt::ScrollUpdate, false); - event.setAccepted(false); -+ event.setTimestamp(timestamp++); - QGuiApplication::sendEvent(window.data(), &event); - } - -@@ -954,6 +960,7 @@ void tst_qquickflickable::trackpad() - QWheelEvent event(pos, window->mapToGlobal(pos), QPoint(0,0), QPoint(0,0), - Qt::NoButton, Qt::NoModifier, Qt::ScrollEnd, false); - event.setAccepted(false); -+ event.setTimestamp(timestamp++); - QGuiApplication::sendEvent(window.data(), &event); - } - -diff --git a/tests/manual/touch/flicktext.qml b/tests/manual/touch/flicktext.qml -index 9e84261687..e69d6207a9 100644 ---- a/tests/manual/touch/flicktext.qml -+++ b/tests/manual/touch/flicktext.qml -@@ -380,6 +380,36 @@ Rectangle { - text: "content X " + flick.contentX.toFixed(2) + " Y " + flick.contentY.toFixed(2) - } - } -+ -+ Column { -+ Row { -+ spacing: 2 -+ Examples.Button { -+ id: decrButton -+ text: "-" -+ onClicked: flick.flickDeceleration -= 100 -+ Timer { -+ running: decrButton.pressed -+ interval: 100; repeat: true -+ onTriggered: flick.flickDeceleration -= 100 -+ } -+ } -+ Text { -+ horizontalAlignment: Text.AlignHCenter -+ text: "decel:\n" + flick.flickDeceleration.toFixed(4) -+ } -+ Examples.Button { -+ id: incrButton -+ text: "+" -+ onClicked: flick.flickDeceleration += 100 -+ } -+ Timer { -+ running: incrButton.pressed -+ interval: 100; repeat: true -+ onTriggered: flick.flickDeceleration += 100 -+ } -+ } -+ } - } - - Component.onCompleted: { --- -2.37.3 - diff --git a/0016-Fix-Flickable-with-QTBUG-56075-patch-applied.patch b/0016-Fix-Flickable-with-QTBUG-56075-patch-applied.patch deleted file mode 100644 index 8eb6c76..0000000 --- a/0016-Fix-Flickable-with-QTBUG-56075-patch-applied.patch +++ /dev/null @@ -1,25 +0,0 @@ -From 46e932d87ffd6b2437b0411dd792112f5d4380fa Mon Sep 17 00:00:00 2001 -From: Wolfgang Frisch -Date: Thu, 19 May 2022 00:55:50 +0200 -Subject: [PATCH 16/18] Fix Flickable with QTBUG-56075 patch applied - ---- - src/quick/items/qquickflickable.cpp | 2 ++ - 1 file changed, 2 insertions(+) - -diff --git a/src/quick/items/qquickflickable.cpp b/src/quick/items/qquickflickable.cpp -index 9eea0e1487..2fa3b7142c 100644 ---- a/src/quick/items/qquickflickable.cpp -+++ b/src/quick/items/qquickflickable.cpp -@@ -62,6 +62,8 @@ - QT_BEGIN_NAMESPACE - - Q_DECLARE_LOGGING_CATEGORY(lcHandlerParent) -+Q_LOGGING_CATEGORY(lcWheel, "qt.quick.flickable.wheel") -+Q_LOGGING_CATEGORY(lcVel, "qt.quick.flickable.velocity") - - // FlickThreshold determines how far the "mouse" must have moved - // before we perform a flick. --- -2.37.3 - diff --git a/0016-Fix-build-after-95290f66b806a307b8da1f72f8fc2c698019.patch b/0016-Fix-build-after-95290f66b806a307b8da1f72f8fc2c698019.patch new file mode 100644 index 0000000..658343b --- /dev/null +++ b/0016-Fix-build-after-95290f66b806a307b8da1f72f8fc2c698019.patch @@ -0,0 +1,26 @@ +From 2574ff9d5c6e72d01dca283e66436cd90a64324d Mon Sep 17 00:00:00 2001 +From: Hannah von Reth +Date: Sat, 5 Nov 2022 18:48:41 +0100 +Subject: [PATCH 16/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(it.value().type()) == QMetaType::QByteArray) + mimeData->setData(it.key(), it.value().toByteArray()); + else + mimeData->setData(it.key(), it.value().toString().toUtf8()); +-- +2.39.0 + diff --git a/0017-Implement-accessibility-for-QQuickWidget.patch b/0017-Implement-accessibility-for-QQuickWidget.patch new file mode 100644 index 0000000..3749a8e --- /dev/null +++ b/0017-Implement-accessibility-for-QQuickWidget.patch @@ -0,0 +1,565 @@ +From 6d1dd8925f160d6ad02ea646eac638675bdf9f1c Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Morten=20Johan=20S=C3=B8rvig?= +Date: Fri, 7 May 2021 10:07:50 +0200 +Subject: [PATCH 17/21] Implement accessibility for QQuickWidget +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +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 +Reviewed-by: Volker Hilsheimer +(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 85719fdc80..eb3df4d4cd 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(); +@@ -188,7 +197,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 ++ ++#include ++ ++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(object)); ++ } else if (classname == QLatin1String("QQuickWidgetOffscreenWindow")) { ++ return new QAccessibleQuickWidgetOffscreenWindow(qobject_cast(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 ++ ++#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 223d91f579..9c97b43518 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.39.0 + diff --git a/0017-Reset-currentChanges-if-currentChanges-is-active-whe.patch b/0017-Reset-currentChanges-if-currentChanges-is-active-whe.patch deleted file mode 100644 index e7c8df8..0000000 --- a/0017-Reset-currentChanges-if-currentChanges-is-active-whe.patch +++ /dev/null @@ -1,38 +0,0 @@ -From 10d77845723f1e7fa60bbb0f60f708949f3a538c Mon Sep 17 00:00:00 2001 -From: Tony Leinonen -Date: Thu, 21 Oct 2021 14:44:02 +0300 -Subject: [PATCH 17/18] Reset currentChanges if currentChanges is active when - refilling listView - -currentIndex was not getting updated because itemViewChangeSet was left -active from previous interaction. Clear the changes if they are still -active on refill. - -Task-number: QTBUG-92809 -Pick-to: 6.2 5.15 -Change-Id: I81558a5e0bfe0f880851fff85370bd5be60a5391 -Reviewed-by: Richard Moe Gustavsen -(cherry picked from commit 2d8033a4ffb9ca60adee29d375491d7ed2a82747) - -* asturmlechner 2021-11-09: Other part of 2d8033a4 is in qtquickcontrols2 - but only consists of tests. ---- - src/quick/items/qquickitemview.cpp | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/src/quick/items/qquickitemview.cpp b/src/quick/items/qquickitemview.cpp -index 13e7b87049..c8ea286d3e 100644 ---- a/src/quick/items/qquickitemview.cpp -+++ b/src/quick/items/qquickitemview.cpp -@@ -1785,7 +1785,7 @@ void QQuickItemViewPrivate::refill(qreal from, qreal to) - - do { - bufferPause.stop(); -- if (currentChanges.hasPendingChanges() || bufferedChanges.hasPendingChanges()) { -+ if (currentChanges.hasPendingChanges() || bufferedChanges.hasPendingChanges() || currentChanges.active) { - currentChanges.reset(); - bufferedChanges.reset(); - releaseVisibleItems(reusableFlag); --- -2.37.3 - diff --git a/0018-Revert-Fix-ListView.isCurrentItem-when-used-with-Del.patch b/0018-Revert-Fix-ListView.isCurrentItem-when-used-with-Del.patch deleted file mode 100644 index d51482e..0000000 --- a/0018-Revert-Fix-ListView.isCurrentItem-when-used-with-Del.patch +++ /dev/null @@ -1,94 +0,0 @@ -From 45d43c04088efb8346979f633f72bb1f23183461 Mon Sep 17 00:00:00 2001 -From: Mitch Curtis -Date: Thu, 4 Nov 2021 10:41:28 +0100 -Subject: [PATCH 18/18] Revert "Fix ListView.isCurrentItem when used with - DelegateModel" -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -This reverts commit d9f9d773e92940786f159897623618f3bf6bcf0f. - -It causes a heap-use-after-free in tst_swipeview.qml. - -Task-number: QTBUG-97423 -Pick-to: 5.15 6.1 6.2 -Change-Id: I42e9831ae1399a010df28c39496a7778121f5e35 -Reviewed-by: Jan Arve Sæther -Reviewed-by: Oliver Eftevaag -(cherry picked from commit 5d656b31eb371c9e0bb97c558f9193b08471f1d7) ---- - src/quick/items/qquickitemview.cpp | 2 -- - .../quick/qquicklistview/data/qtbug86744.qml | 21 ------------------- - .../qquicklistview/tst_qquicklistview.cpp | 14 ------------- - 3 files changed, 37 deletions(-) - delete mode 100644 tests/auto/quick/qquicklistview/data/qtbug86744.qml - -diff --git a/src/quick/items/qquickitemview.cpp b/src/quick/items/qquickitemview.cpp -index c8ea286d3e..f8ad168a17 100644 ---- a/src/quick/items/qquickitemview.cpp -+++ b/src/quick/items/qquickitemview.cpp -@@ -2402,8 +2402,6 @@ void QQuickItemView::createdItem(int index, QObject* object) - d->repositionPackageItemAt(item, index); - else if (index == d->currentIndex) - d->updateCurrent(index); -- } else if (index == d->currentIndex) { -- d->updateCurrent(index); - } - } - -diff --git a/tests/auto/quick/qquicklistview/data/qtbug86744.qml b/tests/auto/quick/qquicklistview/data/qtbug86744.qml -deleted file mode 100644 -index 6dc82d57eb..0000000000 ---- a/tests/auto/quick/qquicklistview/data/qtbug86744.qml -+++ /dev/null -@@ -1,21 +0,0 @@ --import QtQuick 2.15 --import QtQml.Models 2.15 -- --Item { -- height: 200 -- width: 100 -- DelegateModel { -- id: dm -- model: 2 -- delegate: Item { -- width: 100; height: 20 -- property bool isCurrent: ListView.isCurrentItem -- } -- } -- ListView { -- objectName: "listView" -- model: dm -- currentIndex: 1 -- anchors.fill: parent -- } --} -diff --git a/tests/auto/quick/qquicklistview/tst_qquicklistview.cpp b/tests/auto/quick/qquicklistview/tst_qquicklistview.cpp -index df329f8318..b564fd3ba5 100644 ---- a/tests/auto/quick/qquicklistview/tst_qquicklistview.cpp -+++ b/tests/auto/quick/qquicklistview/tst_qquicklistview.cpp -@@ -10201,20 +10201,6 @@ void tst_QQuickListView::dragDelegateWithMouseArea_data() - } - } - --void tst_QQuickListView::isCurrentItem_DelegateModel() --{ -- QScopedPointer window(createView()); -- window->setSource(testFileUrl("qtbug86744.qml")); -- window->resize(640, 480); -- window->show(); -- QVERIFY(QTest::qWaitForWindowExposed(window.data())); -- -- QQuickListView* listView = window->rootObject()->findChild("listView"); -- QVERIFY(listView); -- QVariant value = listView->itemAtIndex(1)->property("isCurrent"); -- QVERIFY(value.toBool() == true); --} -- - QTEST_MAIN(tst_QQuickListView) - - #include "tst_qquicklistview.moc" --- -2.37.3 - diff --git a/0018-Send-ObjectShow-event-for-visible-components-after-i.patch b/0018-Send-ObjectShow-event-for-visible-components-after-i.patch new file mode 100644 index 0000000..0709431 --- /dev/null +++ b/0018-Send-ObjectShow-event-for-visible-components-after-i.patch @@ -0,0 +1,46 @@ +From 99c990d55802c1ea782ca609ccd2bcdf39fb786f Mon Sep 17 00:00:00 2001 +From: Fushan Wen +Date: Sat, 5 Nov 2022 01:44:30 +0800 +Subject: [PATCH 18/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 +(cherry picked from commit 9a4f2d23ecec2c7ff19f83cff28df6b97e3fda98) +--- + 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 9de244ed9e..462147adbd 100644 +--- a/src/quick/items/qquickitem.cpp ++++ b/src/quick/items/qquickitem.cpp +@@ -5125,6 +5125,13 @@ void QQuickItem::componentComplete() + d->addToDirtyList(); + QQuickWindowPrivate::get(d->window)->dirtyItem(this); + } ++ ++#if QT_CONFIG(accessibility) ++ if (d->isAccessible && d->effectiveVisible) { ++ QAccessibleEvent ev(this, QAccessible::ObjectShow); ++ QAccessible::updateAccessibility(&ev); ++ } ++#endif + } + + QQuickStateGroup *QQuickItemPrivate::_states() +-- +2.39.0 + diff --git a/0019-QQuickItem-avoid-emitting-signals-during-destruction.patch b/0019-QQuickItem-avoid-emitting-signals-during-destruction.patch new file mode 100644 index 0000000..00e9eaa --- /dev/null +++ b/0019-QQuickItem-avoid-emitting-signals-during-destruction.patch @@ -0,0 +1,113 @@ +From b91f07532b02f68161ec525bd44501d91ad19b38 Mon Sep 17 00:00:00 2001 +From: Volker Hilsheimer +Date: Wed, 9 Nov 2022 15:34:11 +0100 +Subject: [PATCH 19/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 +Reviewed-by: Mitch Curtis +(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 462147adbd..4cf73ff73d 100644 +--- a/src/quick/items/qquickitem.cpp ++++ b/src/quick/items/qquickitem.cpp +@@ -2327,6 +2327,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(). +@@ -2694,9 +2695,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); + } +@@ -2773,8 +2773,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(); + } + +@@ -2970,7 +2971,8 @@ void QQuickItemPrivate::removeChild(QQuickItem *child) + + itemChange(QQuickItem::ItemChildRemovedChange, child); + +- emit q->childrenChanged(); ++ if (!inDestructor) ++ emit q->childrenChanged(); + } + + void QQuickItemPrivate::refWindow(QQuickWindow *c) +@@ -3199,6 +3201,7 @@ QQuickItemPrivate::QQuickItemPrivate() + , touchEnabled(false) + #endif + , hasCursorHandler(false) ++ , inDestructor(false) + , dirtyAttributes(0) + , nextDirtyItem(nullptr) + , prevDirtyItem(nullptr) +@@ -6118,9 +6121,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 841d91bb40..ade8fb61f2 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.39.0 + diff --git a/0020-a11y-track-item-enabled-state.patch b/0020-a11y-track-item-enabled-state.patch new file mode 100644 index 0000000..817fdc5 --- /dev/null +++ b/0020-a11y-track-item-enabled-state.patch @@ -0,0 +1,57 @@ +From 1fb12800a8907680b821a8e8e29c5b428cbb64b6 Mon Sep 17 00:00:00 2001 +From: Harald Sitter +Date: Mon, 28 Nov 2022 14:59:33 +0100 +Subject: [PATCH 20/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 +Reviewed-by: Jan Arve Sæther +(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 eb3df4d4cd..78e2ab302c 100644 +--- a/src/quick/accessible/qaccessiblequickitem.cpp ++++ b/src/quick/accessible/qaccessiblequickitem.cpp +@@ -210,6 +210,10 @@ QAccessible::State QAccessibleQuickItem::state() const + if (role() == QAccessible::EditableText) + if (auto ti = qobject_cast(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 4cf73ff73d..dec0ae19ae 100644 +--- a/src/quick/items/qquickitem.cpp ++++ b/src/quick/items/qquickitem.cpp +@@ -6174,6 +6174,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.39.0 + diff --git a/0021-Make-QaccessibleQuickWidget-private-API.patch b/0021-Make-QaccessibleQuickWidget-private-API.patch new file mode 100644 index 0000000..2054f05 --- /dev/null +++ b/0021-Make-QaccessibleQuickWidget-private-API.patch @@ -0,0 +1,87 @@ +From 8defe7bfcae2ac5cb6dc25bfe3678124b09cf6f9 Mon Sep 17 00:00:00 2001 +From: Fabian Kosmale +Date: Tue, 1 Jun 2021 16:40:44 +0200 +Subject: [PATCH 21/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 +Reviewed-by: Ulf Hermann +Reviewed-by: Qt CI Bot +(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 + +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.39.0 + diff --git a/qt5-qtdeclarative.spec b/qt5-qtdeclarative.spec index f5f6b75..e4a8644 100644 --- a/qt5-qtdeclarative.spec +++ b/qt5-qtdeclarative.spec @@ -11,7 +11,7 @@ Summary: Qt5 - QtDeclarative component Name: qt5-%{qt_module} -Version: 5.15.7 +Version: 5.15.8 Release: 1%{?dist} # See LICENSE.GPL LICENSE.LGPL LGPL_EXCEPTION.txt, for details @@ -27,25 +27,28 @@ Source5: qv4global_p-multilib.h ## upstream patches ## repo: https://invent.kde.org/qt/qt/qtdeclarative ## branch: kde/5.15 -## git format-patch v5.15.7-lts-lgpl -Patch01: 0001-Document-that-StyledText-also-supports-nbsp-and-quot.patch -Patch02: 0002-Support-apos-in-styled-text.patch -Patch03: 0003-Remove-unused-QPointer-QQuickPointerMask.patch -Patch04: 0004-QQmlDelegateModel-Refresh-the-view-when-a-column-is-.patch -Patch05: 0005-Fix-sweep-step-for-tainted-QObject-JavaScript-wrappe.patch -Patch06: 0006-Revert-Fix-for-possible-crash-in-QSGDefaultLayer-gra.patch -Patch07: 0007-Fix-TapHandler-so-that-it-actually-registers-a-tap.patch -Patch08: 0008-Revert-Fix-TapHandler-so-that-it-actually-registers-.patch -Patch09: 0009-QQmlJs-FixedPoolArray-fix-UB-precondition-violation-.patch -Patch10: 0010-V4-Do-not-call-dtor-of-an-object-we-continue-to-use.patch -Patch11: 0011-Make-sure-QQuickWidget-and-its-offscreen-window-s-sc.patch -Patch12: 0012-QQuickItem-Guard-against-cycles-in-nextPrevItemInTab.patch -Patch13: 0013-QSGOpenGLDistanceFieldGlyphCache-fix-multiplication-.patch -Patch14: 0014-QSGOpenGLDistanceFieldGlyphCache-fix-UB-ordering-of-.patch -Patch15: 0015-Fix-Flickable-wheel-velocity-calculation.patch -Patch16: 0016-Fix-Flickable-with-QTBUG-56075-patch-applied.patch -Patch17: 0017-Reset-currentChanges-if-currentChanges-is-active-whe.patch -Patch18: 0018-Revert-Fix-ListView.isCurrentItem-when-used-with-Del.patch +## git format-patch v5.15.8-lts-lgpl +Patch1: 0001-Document-that-StyledText-also-supports-nbsp-and-quot.patch +Patch2: 0002-Support-apos-in-styled-text.patch +Patch3: 0003-Remove-unused-QPointer-QQuickPointerMask.patch +Patch4: 0004-QQmlDelegateModel-Refresh-the-view-when-a-column-is-.patch +Patch5: 0005-Fix-sweep-step-for-tainted-QObject-JavaScript-wrappe.patch +Patch6: 0006-Fix-TapHandler-so-that-it-actually-registers-a-tap.patch +Patch7: 0007-Revert-Fix-TapHandler-so-that-it-actually-registers-.patch +Patch8: 0008-QQmlJs-FixedPoolArray-fix-UB-precondition-violation-.patch +Patch9: 0009-V4-Do-not-call-dtor-of-an-object-we-continue-to-use.patch +Patch10: 0010-Make-sure-QQuickWidget-and-its-offscreen-window-s-sc.patch +Patch11: 0011-QQuickItem-Guard-against-cycles-in-nextPrevItemInTab.patch +Patch12: 0012-QSGOpenGLDistanceFieldGlyphCache-fix-multiplication-.patch +Patch13: 0013-QSGOpenGLDistanceFieldGlyphCache-fix-UB-ordering-of-.patch +Patch14: 0014-Reset-currentChanges-if-currentChanges-is-active-whe.patch +Patch15: 0015-Don-t-convert-QByteArray-in-startDrag.patch +Patch16: 0016-Fix-build-after-95290f66b806a307b8da1f72f8fc2c698019.patch +Patch17: 0017-Implement-accessibility-for-QQuickWidget.patch +Patch18: 0018-Send-ObjectShow-event-for-visible-components-after-i.patch +Patch19: 0019-QQuickItem-avoid-emitting-signals-during-destruction.patch +Patch20: 0020-a11y-track-item-enabled-state.patch +Patch21: 0021-Make-QaccessibleQuickWidget-private-API.patch ## upstreamable patches @@ -229,6 +232,9 @@ make check -k -C tests ||: %changelog +* Thu Jan 05 2023 Jan Grulich - 5.15.8-1 +- 5.15.8 + * Mon Oct 31 2022 Jan Grulich - 5.15.7-1 - 5.15.7 diff --git a/sources b/sources index 8259c68..7049741 100644 --- a/sources +++ b/sources @@ -1 +1,2 @@ -SHA512 (qtdeclarative-everywhere-opensource-src-5.15.7.tar.xz) = 909721a7c756ad3f55fa30b539ddd7f459449edc599883a4e04acbe6f1cecaf44b3a5f2b3b17adb83adaf8cd3e1e5e7e09829b30b0df3dacb1e203892b996508 +SHA512 (qtdeclarative-everywhere-opensource-src-5.15.6.tar.xz) = a4824b6ec2de5e78819b726850767db6d4280208d6cc985219f4c33b6b0dcd6194557f32b577df97b0596d157190aa9c00e99bf6879554936a356fa7afe8a7d5 +SHA512 (qtdeclarative-everywhere-opensource-src-5.15.8.tar.xz) = c611cc1d25b7eea1da3e5932d253d024459044d8fff6a31066033ea5867dd20aeb183b2d2ba8a2ca71cf263fc1921126509212dd43ab680134e7a9df8d937d73