Add patches
This commit is contained in:
		
							parent
							
								
									d4e39d10f5
								
							
						
					
					
						commit
						faff1df622
					
				
							
								
								
									
										35
									
								
								0001-Remove-unused-QPointer-QQuickPointerMask.patch
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										35
									
								
								0001-Remove-unused-QPointer-QQuickPointerMask.patch
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,35 @@ | |||||||
|  | From adc1d82fbac1f85791977ff42299e1f84f0f8db4 Mon Sep 17 00:00:00 2001 | ||||||
|  | From: Albert Astals Cid <albert.astals.cid@kdab.com> | ||||||
|  | Date: Thu, 17 Jun 2021 16:32:28 +0200 | ||||||
|  | Subject: [PATCH 01/19] Remove unused QPointer<QQuickPointerMask> | ||||||
|  | 
 | ||||||
|  | Change-Id: I009fa6bbd8599dc3bb2e810176fe20e70ed50851 | ||||||
|  | Reviewed-by: Shawn Rutledge <shawn.rutledge@qt.io> | ||||||
|  | (cherry picked from commit ac03b4b8ee9cc8d4522e0c8cf1018ff086f80c1b) | ||||||
|  | ---
 | ||||||
|  |  src/quick/items/qquickmousearea_p_p.h | 2 -- | ||||||
|  |  1 file changed, 2 deletions(-) | ||||||
|  | 
 | ||||||
|  | diff --git a/src/quick/items/qquickmousearea_p_p.h b/src/quick/items/qquickmousearea_p_p.h
 | ||||||
|  | index fba383e268..0d63618622 100644
 | ||||||
|  | --- a/src/quick/items/qquickmousearea_p_p.h
 | ||||||
|  | +++ b/src/quick/items/qquickmousearea_p_p.h
 | ||||||
|  | @@ -61,7 +61,6 @@ QT_BEGIN_NAMESPACE
 | ||||||
|  |   | ||||||
|  |  class QQuickMouseEvent; | ||||||
|  |  class QQuickMouseArea; | ||||||
|  | -class QQuickPointerMask;
 | ||||||
|  |  class QQuickMouseAreaPrivate : public QQuickItemPrivate | ||||||
|  |  { | ||||||
|  |      Q_DECLARE_PUBLIC(QQuickMouseArea) | ||||||
|  | @@ -100,7 +99,6 @@ public:
 | ||||||
|  |  #if QT_CONFIG(quick_draganddrop) | ||||||
|  |      QQuickDrag *drag; | ||||||
|  |  #endif | ||||||
|  | -    QPointer<QQuickPointerMask> mask;
 | ||||||
|  |      QPointF startScene; | ||||||
|  |      QPointF targetStartPos; | ||||||
|  |      QPointF lastPos; | ||||||
|  | -- 
 | ||||||
|  | 2.40.0 | ||||||
|  | 
 | ||||||
							
								
								
									
										178
									
								
								0002-QQmlDelegateModel-Refresh-the-view-when-a-column-is-.patch
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										178
									
								
								0002-QQmlDelegateModel-Refresh-the-view-when-a-column-is-.patch
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,178 @@ | |||||||
|  | From 3784ed7ea1ffe1f4be126b3425841aba44b369d8 Mon Sep 17 00:00:00 2001 | ||||||
|  | From: Aleix Pol <aleixpol@kde.org> | ||||||
|  | Date: Thu, 23 Sep 2021 03:43:04 +0200 | ||||||
|  | Subject: [PATCH 02/19] QQmlDelegateModel: Refresh the view when a column is | ||||||
|  |  added at 0 | ||||||
|  | 
 | ||||||
|  | It can happen that a model reports n>0 rows but columns=0 (See | ||||||
|  | QConcatenateTablesProxyModel). In those cases we would render glitchy | ||||||
|  | items until the elements are marked as dirty. | ||||||
|  | 
 | ||||||
|  | Change-Id: I615c9cacbb1b6f9dee3898b03476605e5ac39d0a | ||||||
|  | Reviewed-by: Ulf Hermann <ulf.hermann@qt.io> | ||||||
|  | (cherry picked from commit ec9251efb918f37971aeefa1f687d137d037ff12) | ||||||
|  | Reviewed-by: Qt Cherry-pick Bot <cherrypick_bot@qt-project.org> | ||||||
|  | Signed-off-by: Aleix Pol <aleixpol@kde.org> | ||||||
|  | ---
 | ||||||
|  |  src/qmlmodels/qqmldelegatemodel.cpp           | 44 +++++++++++++++++++ | ||||||
|  |  src/qmlmodels/qqmldelegatemodel_p.h           |  3 ++ | ||||||
|  |  .../data/redrawUponColumnChange.qml           | 11 +++++ | ||||||
|  |  .../tst_qqmldelegatemodel.cpp                 | 27 ++++++++++++ | ||||||
|  |  4 files changed, 85 insertions(+) | ||||||
|  |  create mode 100644 tests/auto/qml/qqmldelegatemodel/data/redrawUponColumnChange.qml | ||||||
|  | 
 | ||||||
|  | diff --git a/src/qmlmodels/qqmldelegatemodel.cpp b/src/qmlmodels/qqmldelegatemodel.cpp
 | ||||||
|  | index 523c0df779..bc6b2447af 100644
 | ||||||
|  | --- a/src/qmlmodels/qqmldelegatemodel.cpp
 | ||||||
|  | +++ b/src/qmlmodels/qqmldelegatemodel.cpp
 | ||||||
|  | @@ -389,6 +389,12 @@ void QQmlDelegateModelPrivate::connectToAbstractItemModel()
 | ||||||
|  |                        q,  QQmlDelegateModel, SLOT(_q_rowsRemoved(QModelIndex,int,int))); | ||||||
|  |      qmlobject_connect(aim, QAbstractItemModel, SIGNAL(rowsAboutToBeRemoved(QModelIndex,int,int)), | ||||||
|  |                        q,  QQmlDelegateModel, SLOT(_q_rowsAboutToBeRemoved(QModelIndex,int,int))); | ||||||
|  | +    qmlobject_connect(aim, QAbstractItemModel, SIGNAL(columnsInserted(QModelIndex,int,int)),
 | ||||||
|  | +                      q, QQmlDelegateModel, SLOT(_q_columnsInserted(QModelIndex,int,int)));
 | ||||||
|  | +    qmlobject_connect(aim, QAbstractItemModel, SIGNAL(columnsRemoved(QModelIndex,int,int)),
 | ||||||
|  | +                      q, QQmlDelegateModel, SLOT(_q_columnsRemoved(QModelIndex,int,int)));
 | ||||||
|  | +    qmlobject_connect(aim, QAbstractItemModel, SIGNAL(columnsMoved(QModelIndex,int,int,QModelIndex,int)),
 | ||||||
|  | +                      q, QQmlDelegateModel, SLOT(_q_columnsMoved(QModelIndex,int,int,QModelIndex,int)));
 | ||||||
|  |      qmlobject_connect(aim, QAbstractItemModel, SIGNAL(dataChanged(QModelIndex,QModelIndex,QVector<int>)), | ||||||
|  |                        q, QQmlDelegateModel, SLOT(_q_dataChanged(QModelIndex,QModelIndex,QVector<int>))); | ||||||
|  |      qmlobject_connect(aim, QAbstractItemModel, SIGNAL(rowsMoved(QModelIndex,int,int,QModelIndex,int)), | ||||||
|  | @@ -413,6 +419,12 @@ void QQmlDelegateModelPrivate::disconnectFromAbstractItemModel()
 | ||||||
|  |                          q, SLOT(_q_rowsAboutToBeRemoved(QModelIndex,int,int))); | ||||||
|  |      QObject::disconnect(aim, SIGNAL(rowsRemoved(QModelIndex,int,int)), | ||||||
|  |                          q, SLOT(_q_rowsRemoved(QModelIndex,int,int))); | ||||||
|  | +    QObject::disconnect(aim, SIGNAL(columnsInserted(QModelIndex,int,int)), q,
 | ||||||
|  | +                        SLOT(_q_columnsInserted(QModelIndex,int,int)));
 | ||||||
|  | +    QObject::disconnect(aim, SIGNAL(columnsRemoved(QModelIndex,int,int)), q,
 | ||||||
|  | +                        SLOT(_q_columnsRemoved(QModelIndex,int,int)));
 | ||||||
|  | +    QObject::disconnect(aim, SIGNAL(columnsMoved(QModelIndex,int,int,QModelIndex,int)), q,
 | ||||||
|  | +                        SLOT(_q_columnsMoved(QModelIndex,int,int,QModelIndex,int)));
 | ||||||
|  |      QObject::disconnect(aim, SIGNAL(dataChanged(QModelIndex,QModelIndex,QVector<int>)), | ||||||
|  |                          q, SLOT(_q_dataChanged(QModelIndex,QModelIndex,QVector<int>))); | ||||||
|  |      QObject::disconnect(aim, SIGNAL(rowsMoved(QModelIndex,int,int,QModelIndex,int)), | ||||||
|  | @@ -1974,6 +1986,38 @@ void QQmlDelegateModel::_q_rowsMoved(
 | ||||||
|  |      } | ||||||
|  |  } | ||||||
|  |   | ||||||
|  | +void QQmlDelegateModel::_q_columnsInserted(const QModelIndex &parent, int begin, int end)
 | ||||||
|  | +{
 | ||||||
|  | +    Q_D(QQmlDelegateModel);
 | ||||||
|  | +    Q_UNUSED(end);
 | ||||||
|  | +    if (parent == d->m_adaptorModel.rootIndex && begin == 0) {
 | ||||||
|  | +        // mark all items as changed
 | ||||||
|  | +        _q_itemsChanged(0, d->m_count, QVector<int>());
 | ||||||
|  | +    }
 | ||||||
|  | +}
 | ||||||
|  | +
 | ||||||
|  | +void QQmlDelegateModel::_q_columnsRemoved(const QModelIndex &parent, int begin, int end)
 | ||||||
|  | +{
 | ||||||
|  | +    Q_D(QQmlDelegateModel);
 | ||||||
|  | +    Q_UNUSED(end);
 | ||||||
|  | +    if (parent == d->m_adaptorModel.rootIndex && begin == 0) {
 | ||||||
|  | +        // mark all items as changed
 | ||||||
|  | +        _q_itemsChanged(0, d->m_count, QVector<int>());
 | ||||||
|  | +    }
 | ||||||
|  | +}
 | ||||||
|  | +
 | ||||||
|  | +void QQmlDelegateModel::_q_columnsMoved(const QModelIndex &parent, int start, int end,
 | ||||||
|  | +                                        const QModelIndex &destination, int column)
 | ||||||
|  | +{
 | ||||||
|  | +    Q_D(QQmlDelegateModel);
 | ||||||
|  | +    Q_UNUSED(end);
 | ||||||
|  | +    if ((parent == d->m_adaptorModel.rootIndex && start == 0)
 | ||||||
|  | +        || (destination == d->m_adaptorModel.rootIndex && column == 0)) {
 | ||||||
|  | +        // mark all items as changed
 | ||||||
|  | +        _q_itemsChanged(0, d->m_count, QVector<int>());
 | ||||||
|  | +    }
 | ||||||
|  | +}
 | ||||||
|  | +
 | ||||||
|  |  void QQmlDelegateModel::_q_dataChanged(const QModelIndex &begin, const QModelIndex &end, const QVector<int> &roles) | ||||||
|  |  { | ||||||
|  |      Q_D(QQmlDelegateModel); | ||||||
|  | diff --git a/src/qmlmodels/qqmldelegatemodel_p.h b/src/qmlmodels/qqmldelegatemodel_p.h
 | ||||||
|  | index 8aab4badca..d140bfbaaf 100644
 | ||||||
|  | --- a/src/qmlmodels/qqmldelegatemodel_p.h
 | ||||||
|  | +++ b/src/qmlmodels/qqmldelegatemodel_p.h
 | ||||||
|  | @@ -152,6 +152,9 @@ private Q_SLOTS:
 | ||||||
|  |      void _q_itemsMoved(int from, int to, int count); | ||||||
|  |      void _q_modelReset(); | ||||||
|  |      void _q_rowsInserted(const QModelIndex &,int,int); | ||||||
|  | +    void _q_columnsInserted(const QModelIndex &, int, int);
 | ||||||
|  | +    void _q_columnsRemoved(const QModelIndex &, int, int);
 | ||||||
|  | +    void _q_columnsMoved(const QModelIndex &, int, int, const QModelIndex &, int);
 | ||||||
|  |      void _q_rowsAboutToBeRemoved(const QModelIndex &parent, int begin, int end); | ||||||
|  |      void _q_rowsRemoved(const QModelIndex &,int,int); | ||||||
|  |      void _q_rowsMoved(const QModelIndex &, int, int, const QModelIndex &, int); | ||||||
|  | diff --git a/tests/auto/qml/qqmldelegatemodel/data/redrawUponColumnChange.qml b/tests/auto/qml/qqmldelegatemodel/data/redrawUponColumnChange.qml
 | ||||||
|  | new file mode 100644 | ||||||
|  | index 0000000000..206133bb39
 | ||||||
|  | --- /dev/null
 | ||||||
|  | +++ b/tests/auto/qml/qqmldelegatemodel/data/redrawUponColumnChange.qml
 | ||||||
|  | @@ -0,0 +1,11 @@
 | ||||||
|  | +import QtQuick 2.8
 | ||||||
|  | +
 | ||||||
|  | +ListView {
 | ||||||
|  | +    id: root
 | ||||||
|  | +    width: 200
 | ||||||
|  | +    height: 200
 | ||||||
|  | +
 | ||||||
|  | +    delegate: Text {
 | ||||||
|  | +        text: display
 | ||||||
|  | +    }
 | ||||||
|  | +}
 | ||||||
|  | diff --git a/tests/auto/qml/qqmldelegatemodel/tst_qqmldelegatemodel.cpp b/tests/auto/qml/qqmldelegatemodel/tst_qqmldelegatemodel.cpp
 | ||||||
|  | index 35f1e2c94d..1722447830 100644
 | ||||||
|  | --- a/tests/auto/qml/qqmldelegatemodel/tst_qqmldelegatemodel.cpp
 | ||||||
|  | +++ b/tests/auto/qml/qqmldelegatemodel/tst_qqmldelegatemodel.cpp
 | ||||||
|  | @@ -27,6 +27,8 @@
 | ||||||
|  |  ****************************************************************************/ | ||||||
|  |   | ||||||
|  |  #include <QtTest/qtest.h> | ||||||
|  | +#include <QtCore/QConcatenateTablesProxyModel>
 | ||||||
|  | +#include <QtGui/QStandardItemModel>
 | ||||||
|  |  #include <QtQml/qqmlcomponent.h> | ||||||
|  |  #include <QtQmlModels/private/qqmldelegatemodel_p.h> | ||||||
|  |  #include <QtQuick/qquickview.h> | ||||||
|  | @@ -47,6 +49,7 @@ private slots:
 | ||||||
|  |      void filterOnGroup_removeWhenCompleted(); | ||||||
|  |      void qtbug_86017(); | ||||||
|  |      void contextAccessedByHandler(); | ||||||
|  | +    void redrawUponColumnChange();
 | ||||||
|  |  }; | ||||||
|  |   | ||||||
|  |  class AbstractItemModel : public QAbstractItemModel | ||||||
|  | @@ -186,6 +189,30 @@ void tst_QQmlDelegateModel::contextAccessedByHandler()
 | ||||||
|  |      QVERIFY(root->property("works").toBool()); | ||||||
|  |  } | ||||||
|  |   | ||||||
|  | +void tst_QQmlDelegateModel::redrawUponColumnChange()
 | ||||||
|  | +{
 | ||||||
|  | +    QStandardItemModel m1;
 | ||||||
|  | +    m1.appendRow({
 | ||||||
|  | +            new QStandardItem("Banana"),
 | ||||||
|  | +            new QStandardItem("Coconut"),
 | ||||||
|  | +    });
 | ||||||
|  | +
 | ||||||
|  | +    QQuickView view(testFileUrl("redrawUponColumnChange.qml"));
 | ||||||
|  | +    QCOMPARE(view.status(), QQuickView::Ready);
 | ||||||
|  | +    view.show();
 | ||||||
|  | +    QQuickItem *root = view.rootObject();
 | ||||||
|  | +    root->setProperty("model", QVariant::fromValue<QObject *>(&m1));
 | ||||||
|  | +
 | ||||||
|  | +    QObject *item = root->property("currentItem").value<QObject *>();
 | ||||||
|  | +    QVERIFY(item);
 | ||||||
|  | +    QCOMPARE(item->property("text").toString(), "Banana");
 | ||||||
|  | +
 | ||||||
|  | +    QVERIFY(root);
 | ||||||
|  | +    m1.removeColumn(0);
 | ||||||
|  | +
 | ||||||
|  | +    QCOMPARE(item->property("text").toString(), "Coconut");
 | ||||||
|  | +}
 | ||||||
|  | +
 | ||||||
|  |  QTEST_MAIN(tst_QQmlDelegateModel) | ||||||
|  |   | ||||||
|  |  #include "tst_qqmldelegatemodel.moc" | ||||||
|  | -- 
 | ||||||
|  | 2.40.0 | ||||||
|  | 
 | ||||||
| @ -0,0 +1,73 @@ | |||||||
|  | From 18b10527cc14a42a19b5d088845bfd2e96326bbb Mon Sep 17 00:00:00 2001 | ||||||
|  | From: =?UTF-8?q?Jan=20Arve=20S=C3=A6ther?= <jan-arve.saether@qt.io> | ||||||
|  | Date: Thu, 3 Sep 2020 10:51:01 +0200 | ||||||
|  | Subject: [PATCH 03/19] 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 <shawn.rutledge@qt.io> | ||||||
|  | (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<QQuickHandlerPoint> &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.40.0 | ||||||
|  | 
 | ||||||
| @ -0,0 +1,61 @@ | |||||||
|  | From 2842ffc4e6bc4f6a7578866fbbe58c8ceb1efb16 Mon Sep 17 00:00:00 2001 | ||||||
|  | From: Albert Astals Cid <aacid@kde.org> | ||||||
|  | Date: Tue, 16 Nov 2021 22:43:37 +0100 | ||||||
|  | Subject: [PATCH 04/19] 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<QQuickHandlerPoint> &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.40.0 | ||||||
|  | 
 | ||||||
| @ -0,0 +1,84 @@ | |||||||
|  | From 2d50aedb262fd387775575f684eb9e2485d84134 Mon Sep 17 00:00:00 2001 | ||||||
|  | From: Vlad Zahorodnii <vlad.zahorodnii@kde.org> | ||||||
|  | Date: Sat, 29 Jan 2022 21:59:33 +0200 | ||||||
|  | Subject: [PATCH 05/19] 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 <davidedmundson@kde.org> | ||||||
|  | Reviewed-by: Laszlo Agocs <laszlo.agocs@qt.io> | ||||||
|  | (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.40.0 | ||||||
|  | 
 | ||||||
							
								
								
									
										122
									
								
								0006-QQuickItem-Guard-against-cycles-in-nextPrevItemInTab.patch
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										122
									
								
								0006-QQuickItem-Guard-against-cycles-in-nextPrevItemInTab.patch
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,122 @@ | |||||||
|  | From 9a3d7bc6cf8eea575e597ff1af03d87f7fbdc9aa Mon Sep 17 00:00:00 2001 | ||||||
|  | From: Fabian Kosmale <fabian.kosmale@qt.io> | ||||||
|  | Date: Wed, 4 May 2022 09:10:54 +0200 | ||||||
|  | Subject: [PATCH 06/19] 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 <volker.hilsheimer@qt.io> | ||||||
|  | (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 33da9762d3..ec55fb2998 100644
 | ||||||
|  | --- a/src/quick/items/qquickitem.cpp
 | ||||||
|  | +++ b/src/quick/items/qquickitem.cpp
 | ||||||
|  | @@ -59,6 +59,7 @@
 | ||||||
|  |  #include <QtCore/private/qnumeric_p.h> | ||||||
|  |  #include <QtGui/qpa/qplatformtheme.h> | ||||||
|  |  #include <QtCore/qloggingcategory.h> | ||||||
|  | +#include <QtCore/private/qduplicatetracker_p.h>
 | ||||||
|  |   | ||||||
|  |  #include <private/qqmlglobal_p.h> | ||||||
|  |  #include <private/qqmlengine_p.h> | ||||||
|  | @@ -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<QQuickItem *> 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");
 | ||||||
|  | +    QScopedPointer<QQuickView>window(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.40.0 | ||||||
|  | 
 | ||||||
							
								
								
									
										60
									
								
								0007-Don-t-convert-QByteArray-in-startDrag.patch
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										60
									
								
								0007-Don-t-convert-QByteArray-in-startDrag.patch
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,60 @@ | |||||||
|  | From c257eb6a0eeb159c670c9cf6b37d3009ec8879e5 Mon Sep 17 00:00:00 2001 | ||||||
|  | From: Fushan Wen <qydwhotmail@gmail.com> | ||||||
|  | Date: Tue, 1 Nov 2022 22:35:24 +0800 | ||||||
|  | Subject: [PATCH 07/19] Don't convert QByteArray in `startDrag` | ||||||
|  | 
 | ||||||
|  | QMimeData::setData expects the provided data to contain the correctly | ||||||
|  | encoded QByteArray, so if the variant contains a QByteArray, then take | ||||||
|  | it as is to avoid data loss. | ||||||
|  | 
 | ||||||
|  | If the variant is not already a byte array, then we ideally would make | ||||||
|  | sure that the mime type (i.e. the key of the map) and the QVariant's | ||||||
|  | type are compatible (image/png with a QImage works; text/plain with a | ||||||
|  | QImage does not). This changes behavior and needs to be a follow-up | ||||||
|  | commit. | ||||||
|  | 
 | ||||||
|  | Fixes: QTBUG-71922 | ||||||
|  | Change-Id: I9b9f10fd332e1f9568f6835a69a1c359457f823c | ||||||
|  | Reviewed-by: Volker Hilsheimer <volker.hilsheimer@qt.io> | ||||||
|  | (cherry picked from commit 062f9bf57657b54dc708015ec5fed3c89e5cc3ca) | ||||||
|  | Reviewed-by: Qt Cherry-pick Bot <cherrypick_bot@qt-project.org> | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | (cherry picked from commit 22de23c4bb9ac5e2c545e9de3149a7d4f8edd5ee) | ||||||
|  | ---
 | ||||||
|  |  src/quick/items/qquickdrag.cpp | 12 +++++++++--- | ||||||
|  |  1 file changed, 9 insertions(+), 3 deletions(-) | ||||||
|  | 
 | ||||||
|  | diff --git a/src/quick/items/qquickdrag.cpp b/src/quick/items/qquickdrag.cpp
 | ||||||
|  | index 8321fcfeed..3b50370355 100644
 | ||||||
|  | --- a/src/quick/items/qquickdrag.cpp
 | ||||||
|  | +++ b/src/quick/items/qquickdrag.cpp
 | ||||||
|  | @@ -481,7 +481,9 @@ void QQuickDragAttached::setKeys(const QStringList &keys)
 | ||||||
|  |      \qmlattachedproperty stringlist QtQuick::Drag::mimeData | ||||||
|  |      \since 5.2 | ||||||
|  |   | ||||||
|  | -    This property holds a map of mimeData that is used during startDrag.
 | ||||||
|  | +    This property holds a map from mime type to data that is used during startDrag.
 | ||||||
|  | +    The mime data needs to be a \c string, or an \c ArrayBuffer with the data encoded
 | ||||||
|  | +    according to the mime type.
 | ||||||
|  |  */ | ||||||
|  |   | ||||||
|  |  QVariantMap QQuickDragAttached::mimeData() const | ||||||
|  | @@ -766,8 +768,12 @@ Qt::DropAction QQuickDragAttachedPrivate::startDrag(Qt::DropActions supportedAct
 | ||||||
|  |      QDrag *drag = new QDrag(source ? source : q); | ||||||
|  |      QMimeData *mimeData = new QMimeData(); | ||||||
|  |   | ||||||
|  | -    for (auto it = externalMimeData.cbegin(), end = externalMimeData.cend(); it != end; ++it)
 | ||||||
|  | -        mimeData->setData(it.key(), it.value().toString().toUtf8());
 | ||||||
|  | +    for (auto it = externalMimeData.cbegin(), end = externalMimeData.cend(); it != end; ++it) {
 | ||||||
|  | +        if (it.value().typeId() == QMetaType::QByteArray)
 | ||||||
|  | +            mimeData->setData(it.key(), it.value().toByteArray());
 | ||||||
|  | +        else
 | ||||||
|  | +            mimeData->setData(it.key(), it.value().toString().toUtf8());
 | ||||||
|  | +    }
 | ||||||
|  |   | ||||||
|  |      drag->setMimeData(mimeData); | ||||||
|  |      if (pixmapLoader.isReady()) { | ||||||
|  | -- 
 | ||||||
|  | 2.40.0 | ||||||
|  | 
 | ||||||
| @ -0,0 +1,26 @@ | |||||||
|  | From cbb5f2d37a07b75f9d340fd1e1f34a6d1e078eba Mon Sep 17 00:00:00 2001 | ||||||
|  | From: Hannah von Reth <vonreth@kde.org> | ||||||
|  | Date: Sat, 5 Nov 2022 18:48:41 +0100 | ||||||
|  | Subject: [PATCH 08/19] Fix build after | ||||||
|  |  95290f66b806a307b8da1f72f8fc2c69801933d0 | ||||||
|  | 
 | ||||||
|  | ---
 | ||||||
|  |  src/quick/items/qquickdrag.cpp | 2 +- | ||||||
|  |  1 file changed, 1 insertion(+), 1 deletion(-) | ||||||
|  | 
 | ||||||
|  | diff --git a/src/quick/items/qquickdrag.cpp b/src/quick/items/qquickdrag.cpp
 | ||||||
|  | index 3b50370355..383078b3b9 100644
 | ||||||
|  | --- a/src/quick/items/qquickdrag.cpp
 | ||||||
|  | +++ b/src/quick/items/qquickdrag.cpp
 | ||||||
|  | @@ -769,7 +769,7 @@ Qt::DropAction QQuickDragAttachedPrivate::startDrag(Qt::DropActions supportedAct
 | ||||||
|  |      QMimeData *mimeData = new QMimeData(); | ||||||
|  |   | ||||||
|  |      for (auto it = externalMimeData.cbegin(), end = externalMimeData.cend(); it != end; ++it) { | ||||||
|  | -        if (it.value().typeId() == QMetaType::QByteArray)
 | ||||||
|  | +        if (static_cast<QMetaType::Type>(it.value().type()) == QMetaType::QByteArray)
 | ||||||
|  |              mimeData->setData(it.key(), it.value().toByteArray()); | ||||||
|  |          else | ||||||
|  |              mimeData->setData(it.key(), it.value().toString().toUtf8()); | ||||||
|  | -- 
 | ||||||
|  | 2.40.0 | ||||||
|  | 
 | ||||||
							
								
								
									
										565
									
								
								0009-Implement-accessibility-for-QQuickWidget.patch
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										565
									
								
								0009-Implement-accessibility-for-QQuickWidget.patch
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,565 @@ | |||||||
|  | From 3f7ac5540c8796ec2bb2b595ca6648035a0f8b18 Mon Sep 17 00:00:00 2001 | ||||||
|  | From: =?UTF-8?q?Morten=20Johan=20S=C3=B8rvig?= <morten.sorvig@qt.io> | ||||||
|  | Date: Fri, 7 May 2021 10:07:50 +0200 | ||||||
|  | Subject: [PATCH 09/19] 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 <jan-arve.saether@qt.io> | ||||||
|  | Reviewed-by: Volker Hilsheimer <volker.hilsheimer@qt.io> | ||||||
|  | (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 ae1954ae8d..0692ce634d 100644
 | ||||||
|  | --- a/src/quick/accessible/qaccessiblequickitem.cpp
 | ||||||
|  | +++ b/src/quick/accessible/qaccessiblequickitem.cpp
 | ||||||
|  | @@ -46,6 +46,7 @@
 | ||||||
|  |  #include "QtQuick/private/qquicktextinput_p.h" | ||||||
|  |  #include "QtQuick/private/qquickaccessibleattached_p.h" | ||||||
|  |  #include "QtQuick/qquicktextdocument.h" | ||||||
|  | +#include "QtQuick/qquickrendercontrol.h"
 | ||||||
|  |  QT_BEGIN_NAMESPACE | ||||||
|  |   | ||||||
|  |  #if QT_CONFIG(accessibility) | ||||||
|  | @@ -57,7 +58,19 @@ QAccessibleQuickItem::QAccessibleQuickItem(QQuickItem *item)
 | ||||||
|  |   | ||||||
|  |  QWindow *QAccessibleQuickItem::window() const | ||||||
|  |  { | ||||||
|  | -    return item()->window();
 | ||||||
|  | +    QQuickWindow *window = item()->window();
 | ||||||
|  | +
 | ||||||
|  | +    // For QQuickWidget the above window will be the offscreen QQuickWindow,
 | ||||||
|  | +    // which is not a part of the accessibility tree. Detect this case and
 | ||||||
|  | +    // return the window for the QQuickWidget instead.
 | ||||||
|  | +    if (window && !window->handle()) {
 | ||||||
|  | +        if (QQuickRenderControl *renderControl = QQuickWindowPrivate::get(window)->renderControl) {
 | ||||||
|  | +            if (QWindow *renderWindow = renderControl->renderWindow(nullptr))
 | ||||||
|  | +                return renderWindow;
 | ||||||
|  | +        }
 | ||||||
|  | +    }
 | ||||||
|  | +
 | ||||||
|  | +    return window;
 | ||||||
|  |  } | ||||||
|  |   | ||||||
|  |  int QAccessibleQuickItem::childCount() const | ||||||
|  | @@ -113,19 +126,15 @@ QAccessibleInterface *QAccessibleQuickItem::childAt(int x, int y) const
 | ||||||
|  |  QAccessibleInterface *QAccessibleQuickItem::parent() const | ||||||
|  |  { | ||||||
|  |      QQuickItem *parent = item()->parentItem(); | ||||||
|  | -    QQuickWindow *window = item()->window();
 | ||||||
|  | -    QQuickItem *ci = window ? window->contentItem() : nullptr;
 | ||||||
|  | +    QQuickWindow *itemWindow = item()->window();
 | ||||||
|  | +    QQuickItem *ci = itemWindow ? itemWindow->contentItem() : nullptr;
 | ||||||
|  |      while (parent && !QQuickItemPrivate::get(parent)->isAccessible && parent != ci) | ||||||
|  |          parent = parent->parentItem(); | ||||||
|  |   | ||||||
|  |      if (parent) { | ||||||
|  |          if (parent == ci) { | ||||||
|  | -            // Jump out to the scene widget if the parent is the root item.
 | ||||||
|  | -            // There are two root items, QQuickWindow::rootItem and
 | ||||||
|  | -            // QQuickView::declarativeRoot. The former is the true root item,
 | ||||||
|  | -            // but is not a part of the accessibility tree. Check if we hit
 | ||||||
|  | -            // it here and return an interface for the scene instead.
 | ||||||
|  | -            return QAccessible::queryAccessibleInterface(window);
 | ||||||
|  | +            // Jump out to the window if the parent is the root item
 | ||||||
|  | +            return QAccessible::queryAccessibleInterface(window());
 | ||||||
|  |          } else { | ||||||
|  |              while (parent && !parent->d_func()->isAccessible) | ||||||
|  |                  parent = parent->parentItem(); | ||||||
|  | @@ -193,7 +202,7 @@ QAccessible::State QAccessibleQuickItem::state() const
 | ||||||
|  |      QRect viewRect_ = viewRect(); | ||||||
|  |      QRect itemRect = rect(); | ||||||
|  |   | ||||||
|  | -    if (viewRect_.isNull() || itemRect.isNull() || !item()->window() || !item()->window()->isVisible() ||!item()->isVisible() || qFuzzyIsNull(item()->opacity()))
 | ||||||
|  | +    if (viewRect_.isNull() || itemRect.isNull() || !window() || !window()->isVisible() ||!item()->isVisible() || qFuzzyIsNull(item()->opacity()))
 | ||||||
|  |          state.invisible = true; | ||||||
|  |      if (!viewRect_.intersects(itemRect)) | ||||||
|  |          state.offscreen = true; | ||||||
|  | diff --git a/src/quick/accessible/qaccessiblequickview_p.h b/src/quick/accessible/qaccessiblequickview_p.h
 | ||||||
|  | index 39ffcaf39c..8baa01330c 100644
 | ||||||
|  | --- a/src/quick/accessible/qaccessiblequickview_p.h
 | ||||||
|  | +++ b/src/quick/accessible/qaccessiblequickview_p.h
 | ||||||
|  | @@ -58,7 +58,7 @@ QT_BEGIN_NAMESPACE
 | ||||||
|  |   | ||||||
|  |  #if QT_CONFIG(accessibility) | ||||||
|  |   | ||||||
|  | -class QAccessibleQuickWindow : public QAccessibleObject
 | ||||||
|  | +class Q_QUICK_EXPORT QAccessibleQuickWindow : public QAccessibleObject
 | ||||||
|  |  { | ||||||
|  |  public: | ||||||
|  |      QAccessibleQuickWindow(QQuickWindow *object); | ||||||
|  | diff --git a/src/quickwidgets/qaccessiblequickwidget.cpp b/src/quickwidgets/qaccessiblequickwidget.cpp
 | ||||||
|  | new file mode 100644 | ||||||
|  | index 0000000000..6f04d6693f
 | ||||||
|  | --- /dev/null
 | ||||||
|  | +++ b/src/quickwidgets/qaccessiblequickwidget.cpp
 | ||||||
|  | @@ -0,0 +1,110 @@
 | ||||||
|  | +/****************************************************************************
 | ||||||
|  | +**
 | ||||||
|  | +** Copyright (C) 2021 The Qt Company Ltd.
 | ||||||
|  | +** Contact: https://www.qt.io/licensing/
 | ||||||
|  | +**
 | ||||||
|  | +** This file is part of the QtQuick module of the Qt Toolkit.
 | ||||||
|  | +**
 | ||||||
|  | +** $QT_BEGIN_LICENSE:LGPL$
 | ||||||
|  | +** Commercial License Usage
 | ||||||
|  | +** Licensees holding valid commercial Qt licenses may use this file in
 | ||||||
|  | +** accordance with the commercial license agreement provided with the
 | ||||||
|  | +** Software or, alternatively, in accordance with the terms contained in
 | ||||||
|  | +** a written agreement between you and The Qt Company. For licensing terms
 | ||||||
|  | +** and conditions see https://www.qt.io/terms-conditions. For further
 | ||||||
|  | +** information use the contact form at https://www.qt.io/contact-us.
 | ||||||
|  | +**
 | ||||||
|  | +** GNU Lesser General Public License Usage
 | ||||||
|  | +** Alternatively, this file may be used under the terms of the GNU Lesser
 | ||||||
|  | +** General Public License version 3 as published by the Free Software
 | ||||||
|  | +** Foundation and appearing in the file LICENSE.LGPL3 included in the
 | ||||||
|  | +** packaging of this file. Please review the following information to
 | ||||||
|  | +** ensure the GNU Lesser General Public License version 3 requirements
 | ||||||
|  | +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
 | ||||||
|  | +**
 | ||||||
|  | +** GNU General Public License Usage
 | ||||||
|  | +** Alternatively, this file may be used under the terms of the GNU
 | ||||||
|  | +** General Public License version 2.0 or (at your option) the GNU General
 | ||||||
|  | +** Public license version 3 or any later version approved by the KDE Free
 | ||||||
|  | +** Qt Foundation. The licenses are as published by the Free Software
 | ||||||
|  | +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
 | ||||||
|  | +** included in the packaging of this file. Please review the following
 | ||||||
|  | +** information to ensure the GNU General Public License requirements will
 | ||||||
|  | +** be met: https://www.gnu.org/licenses/gpl-2.0.html and
 | ||||||
|  | +** https://www.gnu.org/licenses/gpl-3.0.html.
 | ||||||
|  | +**
 | ||||||
|  | +** $QT_END_LICENSE$
 | ||||||
|  | +**
 | ||||||
|  | +****************************************************************************/
 | ||||||
|  | +
 | ||||||
|  | +#include "qaccessiblequickwidget.h"
 | ||||||
|  | +
 | ||||||
|  | +#include "qquickwidget_p.h"
 | ||||||
|  | +
 | ||||||
|  | +QT_BEGIN_NAMESPACE
 | ||||||
|  | +
 | ||||||
|  | +#if QT_CONFIG(accessibility)
 | ||||||
|  | +
 | ||||||
|  | +QAccessibleQuickWidget::QAccessibleQuickWidget(QQuickWidget* widget)
 | ||||||
|  | +: QAccessibleWidget(widget)
 | ||||||
|  | +, m_accessibleWindow(QQuickWidgetPrivate::get(widget)->offscreenWindow)
 | ||||||
|  | +{
 | ||||||
|  | +    // NOTE: m_accessibleWindow is a QAccessibleQuickWindow, and not a
 | ||||||
|  | +    // QAccessibleQuickWidgetOffscreenWindow (defined below). This means
 | ||||||
|  | +    // it will return the Quick item child interfaces, which is what's needed here
 | ||||||
|  | +    // (unlike QAccessibleQuickWidgetOffscreenWindow, which will report 0 children).
 | ||||||
|  | +}
 | ||||||
|  | +
 | ||||||
|  | +QAccessibleInterface *QAccessibleQuickWidget::child(int index) const
 | ||||||
|  | +{
 | ||||||
|  | +    return m_accessibleWindow.child(index);
 | ||||||
|  | +}
 | ||||||
|  | +
 | ||||||
|  | +int QAccessibleQuickWidget::childCount() const
 | ||||||
|  | +{
 | ||||||
|  | +    return m_accessibleWindow.childCount();
 | ||||||
|  | +}
 | ||||||
|  | +
 | ||||||
|  | +int QAccessibleQuickWidget::indexOfChild(const QAccessibleInterface *iface) const
 | ||||||
|  | +{
 | ||||||
|  | +    return m_accessibleWindow.indexOfChild(iface);
 | ||||||
|  | +}
 | ||||||
|  | +
 | ||||||
|  | +QAccessibleInterface *QAccessibleQuickWidget::childAt(int x, int y) const
 | ||||||
|  | +{
 | ||||||
|  | +    return m_accessibleWindow.childAt(x, y);
 | ||||||
|  | +}
 | ||||||
|  | +
 | ||||||
|  | +QAccessibleQuickWidgetOffscreenWindow::QAccessibleQuickWidgetOffscreenWindow(QQuickWindow *window)
 | ||||||
|  | +:QAccessibleQuickWindow(window)
 | ||||||
|  | +{
 | ||||||
|  | +
 | ||||||
|  | +}
 | ||||||
|  | +
 | ||||||
|  | +QAccessibleInterface *QAccessibleQuickWidgetOffscreenWindow::child(int index) const
 | ||||||
|  | +{
 | ||||||
|  | +    Q_UNUSED(index);
 | ||||||
|  | +    return nullptr;
 | ||||||
|  | +}
 | ||||||
|  | +
 | ||||||
|  | +int QAccessibleQuickWidgetOffscreenWindow::childCount() const
 | ||||||
|  | +{
 | ||||||
|  | +    return 0;
 | ||||||
|  | +}
 | ||||||
|  | +
 | ||||||
|  | +int QAccessibleQuickWidgetOffscreenWindow::indexOfChild(const QAccessibleInterface *iface) const
 | ||||||
|  | +{
 | ||||||
|  | +    Q_UNUSED(iface);
 | ||||||
|  | +    return -1;
 | ||||||
|  | +}
 | ||||||
|  | +
 | ||||||
|  | +QAccessibleInterface *QAccessibleQuickWidgetOffscreenWindow::QAccessibleQuickWidgetOffscreenWindow::childAt(int x, int y) const
 | ||||||
|  | +{
 | ||||||
|  | +    Q_UNUSED(x);
 | ||||||
|  | +    Q_UNUSED(y);
 | ||||||
|  | +    return nullptr;
 | ||||||
|  | +}
 | ||||||
|  | +
 | ||||||
|  | +#endif // accessibility
 | ||||||
|  | +
 | ||||||
|  | +QT_END_NAMESPACE
 | ||||||
|  | diff --git a/src/quickwidgets/qaccessiblequickwidget.h b/src/quickwidgets/qaccessiblequickwidget.h
 | ||||||
|  | new file mode 100644 | ||||||
|  | index 0000000000..1f52c78c46
 | ||||||
|  | --- /dev/null
 | ||||||
|  | +++ b/src/quickwidgets/qaccessiblequickwidget.h
 | ||||||
|  | @@ -0,0 +1,84 @@
 | ||||||
|  | +/****************************************************************************
 | ||||||
|  | +**
 | ||||||
|  | +** Copyright (C) 2021 The Qt Company Ltd.
 | ||||||
|  | +** Contact: https://www.qt.io/licensing/
 | ||||||
|  | +**
 | ||||||
|  | +** This file is part of the QtQuick module of the Qt Toolkit.
 | ||||||
|  | +**
 | ||||||
|  | +** $QT_BEGIN_LICENSE:LGPL$
 | ||||||
|  | +** Commercial License Usage
 | ||||||
|  | +** Licensees holding valid commercial Qt licenses may use this file in
 | ||||||
|  | +** accordance with the commercial license agreement provided with the
 | ||||||
|  | +** Software or, alternatively, in accordance with the terms contained in
 | ||||||
|  | +** a written agreement between you and The Qt Company. For licensing terms
 | ||||||
|  | +** and conditions see https://www.qt.io/terms-conditions. For further
 | ||||||
|  | +** information use the contact form at https://www.qt.io/contact-us.
 | ||||||
|  | +**
 | ||||||
|  | +** GNU Lesser General Public License Usage
 | ||||||
|  | +** Alternatively, this file may be used under the terms of the GNU Lesser
 | ||||||
|  | +** General Public License version 3 as published by the Free Software
 | ||||||
|  | +** Foundation and appearing in the file LICENSE.LGPL3 included in the
 | ||||||
|  | +** packaging of this file. Please review the following information to
 | ||||||
|  | +** ensure the GNU Lesser General Public License version 3 requirements
 | ||||||
|  | +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
 | ||||||
|  | +**
 | ||||||
|  | +** GNU General Public License Usage
 | ||||||
|  | +** Alternatively, this file may be used under the terms of the GNU
 | ||||||
|  | +** General Public License version 2.0 or (at your option) the GNU General
 | ||||||
|  | +** Public license version 3 or any later version approved by the KDE Free
 | ||||||
|  | +** Qt Foundation. The licenses are as published by the Free Software
 | ||||||
|  | +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
 | ||||||
|  | +** included in the packaging of this file. Please review the following
 | ||||||
|  | +** information to ensure the GNU General Public License requirements will
 | ||||||
|  | +** be met: https://www.gnu.org/licenses/gpl-2.0.html and
 | ||||||
|  | +** https://www.gnu.org/licenses/gpl-3.0.html.
 | ||||||
|  | +**
 | ||||||
|  | +** $QT_END_LICENSE$
 | ||||||
|  | +**
 | ||||||
|  | +****************************************************************************/
 | ||||||
|  | +
 | ||||||
|  | +#ifndef QACCESSIBLEQUICKWIDGET_H
 | ||||||
|  | +#define QACCESSIBLEQUICKWIDGET_H
 | ||||||
|  | +
 | ||||||
|  | +#include "qquickwidget.h"
 | ||||||
|  | +#include <QtWidgets/qaccessiblewidget.h>
 | ||||||
|  | +
 | ||||||
|  | +#include <private/qaccessiblequickview_p.h>
 | ||||||
|  | +
 | ||||||
|  | +QT_BEGIN_NAMESPACE
 | ||||||
|  | +
 | ||||||
|  | +#if QT_CONFIG(accessibility)
 | ||||||
|  | +
 | ||||||
|  | +// These classes implement the QQuickWiget accessibility switcharoo,
 | ||||||
|  | +// where the child items of the QQuickWidgetOffscreenWindow are reported
 | ||||||
|  | +// as child accessible interfaces of the QAccessibleQuickWidget.
 | ||||||
|  | +class QAccessibleQuickWidget: public QAccessibleWidget
 | ||||||
|  | +{
 | ||||||
|  | +public:
 | ||||||
|  | +    QAccessibleQuickWidget(QQuickWidget* widget);
 | ||||||
|  | +
 | ||||||
|  | +    QAccessibleInterface *child(int index) const override;
 | ||||||
|  | +    int childCount() const override;
 | ||||||
|  | +    int indexOfChild(const QAccessibleInterface *iface) const override;
 | ||||||
|  | +    QAccessibleInterface *childAt(int x, int y) const override;
 | ||||||
|  | +
 | ||||||
|  | +private:
 | ||||||
|  | +    QAccessibleQuickWindow m_accessibleWindow;
 | ||||||
|  | +    Q_DISABLE_COPY(QAccessibleQuickWidget)
 | ||||||
|  | +};
 | ||||||
|  | +
 | ||||||
|  | +class QAccessibleQuickWidgetOffscreenWindow: public QAccessibleQuickWindow
 | ||||||
|  | +{
 | ||||||
|  | +public:
 | ||||||
|  | +    QAccessibleQuickWidgetOffscreenWindow(QQuickWindow *window);
 | ||||||
|  | +    QAccessibleInterface *child(int index) const override;
 | ||||||
|  | +    int childCount() const override;
 | ||||||
|  | +    int indexOfChild(const QAccessibleInterface *iface) const override;
 | ||||||
|  | +    QAccessibleInterface *childAt(int x, int y) const override;
 | ||||||
|  | +};
 | ||||||
|  | +
 | ||||||
|  | +#endif // accessibility
 | ||||||
|  | +
 | ||||||
|  | +QT_END_NAMESPACE
 | ||||||
|  | +
 | ||||||
|  | +#endif
 | ||||||
|  | diff --git a/src/quickwidgets/qaccessiblequickwidgetfactory.cpp b/src/quickwidgets/qaccessiblequickwidgetfactory.cpp
 | ||||||
|  | new file mode 100644 | ||||||
|  | index 0000000000..3756d0c27c
 | ||||||
|  | --- /dev/null
 | ||||||
|  | +++ b/src/quickwidgets/qaccessiblequickwidgetfactory.cpp
 | ||||||
|  | @@ -0,0 +1,60 @@
 | ||||||
|  | +/****************************************************************************
 | ||||||
|  | +**
 | ||||||
|  | +** Copyright (C) 2021 The Qt Company Ltd.
 | ||||||
|  | +** Contact: https://www.qt.io/licensing/
 | ||||||
|  | +**
 | ||||||
|  | +** This file is part of the QtQuick module of the Qt Toolkit.
 | ||||||
|  | +**
 | ||||||
|  | +** $QT_BEGIN_LICENSE:LGPL$
 | ||||||
|  | +** Commercial License Usage
 | ||||||
|  | +** Licensees holding valid commercial Qt licenses may use this file in
 | ||||||
|  | +** accordance with the commercial license agreement provided with the
 | ||||||
|  | +** Software or, alternatively, in accordance with the terms contained in
 | ||||||
|  | +** a written agreement between you and The Qt Company. For licensing terms
 | ||||||
|  | +** and conditions see https://www.qt.io/terms-conditions. For further
 | ||||||
|  | +** information use the contact form at https://www.qt.io/contact-us.
 | ||||||
|  | +**
 | ||||||
|  | +** GNU Lesser General Public License Usage
 | ||||||
|  | +** Alternatively, this file may be used under the terms of the GNU Lesser
 | ||||||
|  | +** General Public License version 3 as published by the Free Software
 | ||||||
|  | +** Foundation and appearing in the file LICENSE.LGPL3 included in the
 | ||||||
|  | +** packaging of this file. Please review the following information to
 | ||||||
|  | +** ensure the GNU Lesser General Public License version 3 requirements
 | ||||||
|  | +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
 | ||||||
|  | +**
 | ||||||
|  | +** GNU General Public License Usage
 | ||||||
|  | +** Alternatively, this file may be used under the terms of the GNU
 | ||||||
|  | +** General Public License version 2.0 or (at your option) the GNU General
 | ||||||
|  | +** Public license version 3 or any later version approved by the KDE Free
 | ||||||
|  | +** Qt Foundation. The licenses are as published by the Free Software
 | ||||||
|  | +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
 | ||||||
|  | +** included in the packaging of this file. Please review the following
 | ||||||
|  | +** information to ensure the GNU General Public License requirements will
 | ||||||
|  | +** be met: https://www.gnu.org/licenses/gpl-2.0.html and
 | ||||||
|  | +** https://www.gnu.org/licenses/gpl-3.0.html.
 | ||||||
|  | +**
 | ||||||
|  | +** $QT_END_LICENSE$
 | ||||||
|  | +**
 | ||||||
|  | +****************************************************************************/
 | ||||||
|  | +
 | ||||||
|  | +#include "qaccessiblequickwidgetfactory_p.h"
 | ||||||
|  | +#include "qaccessiblequickwidget.h"
 | ||||||
|  | +
 | ||||||
|  | +QT_BEGIN_NAMESPACE
 | ||||||
|  | +
 | ||||||
|  | +#if QT_CONFIG(accessibility)
 | ||||||
|  | +
 | ||||||
|  | +QAccessibleInterface *qAccessibleQuickWidgetFactory(const QString &classname, QObject *object)
 | ||||||
|  | +{
 | ||||||
|  | +    if (classname == QLatin1String("QQuickWidget")) {
 | ||||||
|  | +        return new QAccessibleQuickWidget(qobject_cast<QQuickWidget *>(object));
 | ||||||
|  | +    } else if (classname == QLatin1String("QQuickWidgetOffscreenWindow")) {
 | ||||||
|  | +        return new QAccessibleQuickWidgetOffscreenWindow(qobject_cast<QQuickWindow *>(object));
 | ||||||
|  | +    }
 | ||||||
|  | +    return 0;
 | ||||||
|  | +}
 | ||||||
|  | +
 | ||||||
|  | +#endif // accessibility
 | ||||||
|  | +
 | ||||||
|  | +QT_END_NAMESPACE
 | ||||||
|  | +
 | ||||||
|  | diff --git a/src/quickwidgets/qaccessiblequickwidgetfactory_p.h b/src/quickwidgets/qaccessiblequickwidgetfactory_p.h
 | ||||||
|  | new file mode 100644 | ||||||
|  | index 0000000000..8c63b09f81
 | ||||||
|  | --- /dev/null
 | ||||||
|  | +++ b/src/quickwidgets/qaccessiblequickwidgetfactory_p.h
 | ||||||
|  | @@ -0,0 +1,66 @@
 | ||||||
|  | +/****************************************************************************
 | ||||||
|  | +**
 | ||||||
|  | +** Copyright (C) 2021 The Qt Company Ltd.
 | ||||||
|  | +** Contact: https://www.qt.io/licensing/
 | ||||||
|  | +**
 | ||||||
|  | +** This file is part of the QtQuick module of the Qt Toolkit.
 | ||||||
|  | +**
 | ||||||
|  | +** $QT_BEGIN_LICENSE:LGPL$
 | ||||||
|  | +** Commercial License Usage
 | ||||||
|  | +** Licensees holding valid commercial Qt licenses may use this file in
 | ||||||
|  | +** accordance with the commercial license agreement provided with the
 | ||||||
|  | +** Software or, alternatively, in accordance with the terms contained in
 | ||||||
|  | +** a written agreement between you and The Qt Company. For licensing terms
 | ||||||
|  | +** and conditions see https://www.qt.io/terms-conditions. For further
 | ||||||
|  | +** information use the contact form at https://www.qt.io/contact-us.
 | ||||||
|  | +**
 | ||||||
|  | +** GNU Lesser General Public License Usage
 | ||||||
|  | +** Alternatively, this file may be used under the terms of the GNU Lesser
 | ||||||
|  | +** General Public License version 3 as published by the Free Software
 | ||||||
|  | +** Foundation and appearing in the file LICENSE.LGPL3 included in the
 | ||||||
|  | +** packaging of this file. Please review the following information to
 | ||||||
|  | +** ensure the GNU Lesser General Public License version 3 requirements
 | ||||||
|  | +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
 | ||||||
|  | +**
 | ||||||
|  | +** GNU General Public License Usage
 | ||||||
|  | +** Alternatively, this file may be used under the terms of the GNU
 | ||||||
|  | +** General Public License version 2.0 or (at your option) the GNU General
 | ||||||
|  | +** Public license version 3 or any later version approved by the KDE Free
 | ||||||
|  | +** Qt Foundation. The licenses are as published by the Free Software
 | ||||||
|  | +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
 | ||||||
|  | +** included in the packaging of this file. Please review the following
 | ||||||
|  | +** information to ensure the GNU General Public License requirements will
 | ||||||
|  | +** be met: https://www.gnu.org/licenses/gpl-2.0.html and
 | ||||||
|  | +** https://www.gnu.org/licenses/gpl-3.0.html.
 | ||||||
|  | +**
 | ||||||
|  | +** $QT_END_LICENSE$
 | ||||||
|  | +**
 | ||||||
|  | +****************************************************************************/
 | ||||||
|  | +
 | ||||||
|  | +#include <QtGui/qaccessible.h>
 | ||||||
|  | +
 | ||||||
|  | +#ifndef QACCESSIBLEQUICKWIDGETFACTORY_H
 | ||||||
|  | +#define QACCESSIBLEQUICKWIDGETFACTORY_H
 | ||||||
|  | +
 | ||||||
|  | +//
 | ||||||
|  | +//  W A R N I N G
 | ||||||
|  | +//  -------------
 | ||||||
|  | +//
 | ||||||
|  | +// This file is not part of the Qt API.  It exists purely as an
 | ||||||
|  | +// implementation detail.  This header file may change from version to
 | ||||||
|  | +// version without notice, or even be removed.
 | ||||||
|  | +//
 | ||||||
|  | +// We mean it.
 | ||||||
|  | +//
 | ||||||
|  | +
 | ||||||
|  | +QT_BEGIN_NAMESPACE
 | ||||||
|  | +
 | ||||||
|  | +#if QT_CONFIG(accessibility)
 | ||||||
|  | +
 | ||||||
|  | +QAccessibleInterface *qAccessibleQuickWidgetFactory(const QString &classname, QObject *object);
 | ||||||
|  | +
 | ||||||
|  | +#endif
 | ||||||
|  | +
 | ||||||
|  | +QT_END_NAMESPACE
 | ||||||
|  | +
 | ||||||
|  | +#endif
 | ||||||
|  | diff --git a/src/quickwidgets/qquickwidget.cpp b/src/quickwidgets/qquickwidget.cpp
 | ||||||
|  | index 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.40.0 | ||||||
|  | 
 | ||||||
| @ -0,0 +1,46 @@ | |||||||
|  | From bdb3af04019b9134d6e815f4fe54317db63d0152 Mon Sep 17 00:00:00 2001 | ||||||
|  | From: Fushan Wen <qydwhotmail@gmail.com> | ||||||
|  | Date: Sat, 5 Nov 2022 01:44:30 +0800 | ||||||
|  | Subject: [PATCH 10/19] Send ObjectShow event for visible components after | ||||||
|  |  initialized | ||||||
|  | MIME-Version: 1.0 | ||||||
|  | Content-Type: text/plain; charset=UTF-8 | ||||||
|  | Content-Transfer-Encoding: 8bit | ||||||
|  | 
 | ||||||
|  | Currently ObjectShow event is only sent when the visible property | ||||||
|  | changes from false to true, but for items with the notification | ||||||
|  | accessible role, a screen reader like Orca needs to receive an | ||||||
|  | ObjectShow event to read the notification, so also send the event after | ||||||
|  | a component is initialized. | ||||||
|  | 
 | ||||||
|  | See also: https://gitlab.gnome.org/GNOME/orca/-/merge_requests/134 | ||||||
|  | 
 | ||||||
|  | Pick-to: 6.4 | ||||||
|  | Change-Id: I626594b65ffe4d0582dcee9f489df0c2c63e53b7 | ||||||
|  | Reviewed-by: Jan Arve Sæther <jan-arve.saether@qt.io> | ||||||
|  | (cherry picked from commit 9a4f2d23ecec2c7ff19f83cff28df6b97e3fda98) | ||||||
|  | ---
 | ||||||
|  |  src/quick/items/qquickitem.cpp | 7 +++++++ | ||||||
|  |  1 file changed, 7 insertions(+) | ||||||
|  | 
 | ||||||
|  | diff --git a/src/quick/items/qquickitem.cpp b/src/quick/items/qquickitem.cpp
 | ||||||
|  | index ec55fb2998..499fb61d1b 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.40.0 | ||||||
|  | 
 | ||||||
							
								
								
									
										113
									
								
								0011-QQuickItem-avoid-emitting-signals-during-destruction.patch
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										113
									
								
								0011-QQuickItem-avoid-emitting-signals-during-destruction.patch
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,113 @@ | |||||||
|  | From 19afcf36b92dc36e83b613e4b9ee383f6beb02dc Mon Sep 17 00:00:00 2001 | ||||||
|  | From: Volker Hilsheimer <volker.hilsheimer@qt.io> | ||||||
|  | Date: Wed, 9 Nov 2022 15:34:11 +0100 | ||||||
|  | Subject: [PATCH 11/19] QQuickItem: avoid emitting signals during destruction | ||||||
|  | 
 | ||||||
|  | If a QQuickItem is in the QQuickItem destructor, then it is both unsafe | ||||||
|  | and unnecessary to emit property change notifications. Connected code | ||||||
|  | can no longer rely on the state of the emitting object - if it was | ||||||
|  | originally a subclass of QQuickItem, then those subclass destructors | ||||||
|  | will already have run. And the QQuickItem destructor will also have | ||||||
|  | partially run, leaving the object in an undefined state. | ||||||
|  | 
 | ||||||
|  | Add a flag that we set to true at the top of ~QQuickItem, and don't emit | ||||||
|  | visibleChildrenChanged, parentChanged, visibleChanged, and | ||||||
|  | childrenChanged for items that are partially destroyed already. | ||||||
|  | 
 | ||||||
|  | [ChangeLog][Qt Quick][QQuickItem] QQuickItem no longer emits change | ||||||
|  | notifications for the parent, children, visible, and visibleChildren | ||||||
|  | properties while it is being destroyed. | ||||||
|  | 
 | ||||||
|  | Task-number: QTBUG-107850 | ||||||
|  | Change-Id: I36ea98842c89ad89fcc1c4a328d138f66f2a0446 | ||||||
|  | Reviewed-by: Shawn Rutledge <shawn.rutledge@qt.io> | ||||||
|  | Reviewed-by: Mitch Curtis <mitch.curtis@qt.io> | ||||||
|  | (cherry picked from commit 74873324bdf3399753f9fcaf7461c0e00df628b1) | ||||||
|  | ---
 | ||||||
|  |  src/quick/items/qquickitem.cpp | 21 +++++++++++++-------- | ||||||
|  |  src/quick/items/qquickitem_p.h |  1 + | ||||||
|  |  2 files changed, 14 insertions(+), 8 deletions(-) | ||||||
|  | 
 | ||||||
|  | diff --git a/src/quick/items/qquickitem.cpp b/src/quick/items/qquickitem.cpp
 | ||||||
|  | index 499fb61d1b..5ee2a440a3 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.40.0 | ||||||
|  | 
 | ||||||
							
								
								
									
										57
									
								
								0012-a11y-track-item-enabled-state.patch
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										57
									
								
								0012-a11y-track-item-enabled-state.patch
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,57 @@ | |||||||
|  | From 5ed173f4ba070bca6c9ec3335b84cc322885b01d Mon Sep 17 00:00:00 2001 | ||||||
|  | From: Harald Sitter <sitter@kde.org> | ||||||
|  | Date: Mon, 28 Nov 2022 14:59:33 +0100 | ||||||
|  | Subject: [PATCH 12/19] a11y: track item enabled state | ||||||
|  | MIME-Version: 1.0 | ||||||
|  | Content-Type: text/plain; charset=UTF-8 | ||||||
|  | Content-Transfer-Encoding: 8bit | ||||||
|  | 
 | ||||||
|  | disabled items are neither enabled nor focusable | ||||||
|  | 
 | ||||||
|  | Change-Id: I4f286c7b85605d5ad6fa787d1f5cfcce1297d268 | ||||||
|  | Reviewed-by: Volker Hilsheimer <volker.hilsheimer@qt.io> | ||||||
|  | Reviewed-by: Jan Arve Sæther <jan-arve.saether@qt.io> | ||||||
|  | (cherry picked from commit 20fd2902a6d7bdb4a3306005d2718ca5a8fef96d) | ||||||
|  | ---
 | ||||||
|  |  src/quick/accessible/qaccessiblequickitem.cpp | 4 ++++ | ||||||
|  |  src/quick/items/qquickitem.cpp                | 9 +++++++++ | ||||||
|  |  2 files changed, 13 insertions(+) | ||||||
|  | 
 | ||||||
|  | diff --git a/src/quick/accessible/qaccessiblequickitem.cpp b/src/quick/accessible/qaccessiblequickitem.cpp
 | ||||||
|  | index 0692ce634d..a8df58d450 100644
 | ||||||
|  | --- a/src/quick/accessible/qaccessiblequickitem.cpp
 | ||||||
|  | +++ b/src/quick/accessible/qaccessiblequickitem.cpp
 | ||||||
|  | @@ -215,6 +215,10 @@ QAccessible::State QAccessibleQuickItem::state() const
 | ||||||
|  |      if (role() == QAccessible::EditableText) | ||||||
|  |          if (auto ti = qobject_cast<QQuickTextInput *>(item())) | ||||||
|  |              state.passwordEdit = ti->echoMode() != QQuickTextInput::Normal; | ||||||
|  | +    if (!item()->isEnabled()) {
 | ||||||
|  | +        state.focusable = false;
 | ||||||
|  | +        state.disabled = true;
 | ||||||
|  | +    }
 | ||||||
|  |      return state; | ||||||
|  |  } | ||||||
|  |   | ||||||
|  | diff --git a/src/quick/items/qquickitem.cpp b/src/quick/items/qquickitem.cpp
 | ||||||
|  | index 5ee2a440a3..c370d6e5c3 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.40.0 | ||||||
|  | 
 | ||||||
							
								
								
									
										87
									
								
								0013-Make-QaccessibleQuickWidget-private-API.patch
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										87
									
								
								0013-Make-QaccessibleQuickWidget-private-API.patch
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,87 @@ | |||||||
|  | From a8fa6c930597b633367777044f4c0328012f6bd5 Mon Sep 17 00:00:00 2001 | ||||||
|  | From: Fabian Kosmale <fabian.kosmale@qt.io> | ||||||
|  | Date: Tue, 1 Jun 2021 16:40:44 +0200 | ||||||
|  | Subject: [PATCH 13/19] Make QaccessibleQuickWidget private API | ||||||
|  | 
 | ||||||
|  | Its base class is private API, so it should be private API, too. | ||||||
|  | 
 | ||||||
|  | Change-Id: Ic80f841fee19ed0305c60ad5f8e9349a05f09e5e | ||||||
|  | Reviewed-by: Alexandru Croitor <alexandru.croitor@qt.io> | ||||||
|  | Reviewed-by: Ulf Hermann <ulf.hermann@qt.io> | ||||||
|  | Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org> | ||||||
|  | (cherry picked from commit a4fa74d3e7581cb5c6bb82223ee17257f66fa41d) | ||||||
|  | ---
 | ||||||
|  |  src/quickwidgets/qaccessiblequickwidget.cpp           |  2 +- | ||||||
|  |  ...ssiblequickwidget.h => qaccessiblequickwidget_p.h} | 11 +++++++++++ | ||||||
|  |  src/quickwidgets/qaccessiblequickwidgetfactory.cpp    |  2 +- | ||||||
|  |  src/quickwidgets/quickwidgets.pro                     |  2 +- | ||||||
|  |  4 files changed, 14 insertions(+), 3 deletions(-) | ||||||
|  |  rename src/quickwidgets/{qaccessiblequickwidget.h => qaccessiblequickwidget_p.h} (92%) | ||||||
|  | 
 | ||||||
|  | diff --git a/src/quickwidgets/qaccessiblequickwidget.cpp b/src/quickwidgets/qaccessiblequickwidget.cpp
 | ||||||
|  | index 6f04d6693f..8a1c901880 100644
 | ||||||
|  | --- a/src/quickwidgets/qaccessiblequickwidget.cpp
 | ||||||
|  | +++ b/src/quickwidgets/qaccessiblequickwidget.cpp
 | ||||||
|  | @@ -37,7 +37,7 @@
 | ||||||
|  |  ** | ||||||
|  |  ****************************************************************************/ | ||||||
|  |   | ||||||
|  | -#include "qaccessiblequickwidget.h"
 | ||||||
|  | +#include "qaccessiblequickwidget_p.h"
 | ||||||
|  |   | ||||||
|  |  #include "qquickwidget_p.h" | ||||||
|  |   | ||||||
|  | diff --git a/src/quickwidgets/qaccessiblequickwidget.h b/src/quickwidgets/qaccessiblequickwidget_p.h
 | ||||||
|  | similarity index 92% | ||||||
|  | rename from src/quickwidgets/qaccessiblequickwidget.h | ||||||
|  | rename to src/quickwidgets/qaccessiblequickwidget_p.h | ||||||
|  | index 1f52c78c46..7c2ab930e0 100644
 | ||||||
|  | --- a/src/quickwidgets/qaccessiblequickwidget.h
 | ||||||
|  | +++ b/src/quickwidgets/qaccessiblequickwidget_p.h
 | ||||||
|  | @@ -40,6 +40,17 @@
 | ||||||
|  |  #ifndef QACCESSIBLEQUICKWIDGET_H | ||||||
|  |  #define QACCESSIBLEQUICKWIDGET_H | ||||||
|  |   | ||||||
|  | +//
 | ||||||
|  | +//  W A R N I N G
 | ||||||
|  | +//  -------------
 | ||||||
|  | +//
 | ||||||
|  | +// This file is not part of the Qt API.  It exists purely as an
 | ||||||
|  | +// implementation detail.  This header file may change from version to
 | ||||||
|  | +// version without notice, or even be removed.
 | ||||||
|  | +//
 | ||||||
|  | +// We mean it.
 | ||||||
|  | +//
 | ||||||
|  | +
 | ||||||
|  |  #include "qquickwidget.h" | ||||||
|  |  #include <QtWidgets/qaccessiblewidget.h> | ||||||
|  |   | ||||||
|  | diff --git a/src/quickwidgets/qaccessiblequickwidgetfactory.cpp b/src/quickwidgets/qaccessiblequickwidgetfactory.cpp
 | ||||||
|  | index 3756d0c27c..7ba88a1769 100644
 | ||||||
|  | --- a/src/quickwidgets/qaccessiblequickwidgetfactory.cpp
 | ||||||
|  | +++ b/src/quickwidgets/qaccessiblequickwidgetfactory.cpp
 | ||||||
|  | @@ -38,7 +38,7 @@
 | ||||||
|  |  ****************************************************************************/ | ||||||
|  |   | ||||||
|  |  #include "qaccessiblequickwidgetfactory_p.h" | ||||||
|  | -#include "qaccessiblequickwidget.h"
 | ||||||
|  | +#include "qaccessiblequickwidget_p.h"
 | ||||||
|  |   | ||||||
|  |  QT_BEGIN_NAMESPACE | ||||||
|  |   | ||||||
|  | diff --git a/src/quickwidgets/quickwidgets.pro b/src/quickwidgets/quickwidgets.pro
 | ||||||
|  | index f46deb54ac..85d156b8a3 100644
 | ||||||
|  | --- a/src/quickwidgets/quickwidgets.pro
 | ||||||
|  | +++ b/src/quickwidgets/quickwidgets.pro
 | ||||||
|  | @@ -8,7 +8,7 @@ HEADERS += \
 | ||||||
|  |      qquickwidget.h \ | ||||||
|  |      qquickwidget_p.h \ | ||||||
|  |      qtquickwidgetsglobal.h \ | ||||||
|  | -    qaccessiblequickwidget.h \
 | ||||||
|  | +    qaccessiblequickwidget_p.h \
 | ||||||
|  |      qaccessiblequickwidgetfactory_p.h | ||||||
|  |   | ||||||
|  |  SOURCES += \ | ||||||
|  | -- 
 | ||||||
|  | 2.40.0 | ||||||
|  | 
 | ||||||
							
								
								
									
										113
									
								
								0014-Qml-Don-t-crash-when-as-casting-to-type-with-errors.patch
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										113
									
								
								0014-Qml-Don-t-crash-when-as-casting-to-type-with-errors.patch
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,113 @@ | |||||||
|  | From 7be5422134167fe6d9fd44ef683f407bbda1bce7 Mon Sep 17 00:00:00 2001 | ||||||
|  | From: Ulf Hermann <ulf.hermann@qt.io> | ||||||
|  | Date: Tue, 30 Nov 2021 14:39:48 +0100 | ||||||
|  | Subject: [PATCH 14/19] Qml: Don't crash when as-casting to type with errors | ||||||
|  | 
 | ||||||
|  | Such types don't have a compilation unit, but we still know their names. | ||||||
|  | 
 | ||||||
|  | Pick-to: 6.2 | ||||||
|  | Fixes: QTBUG-98792 | ||||||
|  | Change-Id: I2db8dea3a5a02ec1492f7f7a054fd3ad4c6ad69a | ||||||
|  | Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io> | ||||||
|  | Reviewed-by: Mitch Curtis <mitch.curtis@qt.io> | ||||||
|  | (cherry picked from commit e0cd201e91ae64b9c03e0128cd17656b00611fbb) | ||||||
|  | ---
 | ||||||
|  |  src/qml/qml/qqmltypewrapper.cpp                  |  6 ++++-- | ||||||
|  |  src/qml/types/qqmlconnections.cpp                |  2 +- | ||||||
|  |  tests/auto/qml/qqmllanguage/data/Broken.qml      |  5 +++++ | ||||||
|  |  tests/auto/qml/qqmllanguage/data/asBroken.qml    |  6 ++++++ | ||||||
|  |  tests/auto/qml/qqmllanguage/tst_qqmllanguage.cpp | 16 ++++++++++++++++ | ||||||
|  |  5 files changed, 32 insertions(+), 3 deletions(-) | ||||||
|  |  create mode 100644 tests/auto/qml/qqmllanguage/data/Broken.qml | ||||||
|  |  create mode 100644 tests/auto/qml/qqmllanguage/data/asBroken.qml | ||||||
|  | 
 | ||||||
|  | diff --git a/src/qml/qml/qqmltypewrapper.cpp b/src/qml/qml/qqmltypewrapper.cpp
 | ||||||
|  | index 175de8b936..a6ba4b8cb3 100644
 | ||||||
|  | --- a/src/qml/qml/qqmltypewrapper.cpp
 | ||||||
|  | +++ b/src/qml/qml/qqmltypewrapper.cpp
 | ||||||
|  | @@ -419,8 +419,10 @@ ReturnedValue QQmlTypeWrapper::virtualInstanceOf(const Object *typeObject, const
 | ||||||
|  |              return Encode(false); | ||||||
|  |   | ||||||
|  |          QQmlRefPointer<QQmlTypeData> td = qenginepriv->typeLoader.getType(typeWrapper->d()->type().sourceUrl()); | ||||||
|  | -        ExecutableCompilationUnit *cu = td->compilationUnit();
 | ||||||
|  | -        myQmlType = qenginepriv->metaObjectForType(cu->metaTypeId);
 | ||||||
|  | +        if (ExecutableCompilationUnit *cu = td->compilationUnit())
 | ||||||
|  | +            myQmlType = qenginepriv->metaObjectForType(cu->metaTypeId);
 | ||||||
|  | +        else
 | ||||||
|  | +            return Encode(false); // It seems myQmlType has some errors, so we could not compile it.
 | ||||||
|  |      } else { | ||||||
|  |          myQmlType = qenginepriv->metaObjectForType(myTypeId); | ||||||
|  |      } | ||||||
|  | diff --git a/src/qml/types/qqmlconnections.cpp b/src/qml/types/qqmlconnections.cpp
 | ||||||
|  | index 29ed62cd39..aba930dfe1 100644
 | ||||||
|  | --- a/src/qml/types/qqmlconnections.cpp
 | ||||||
|  | +++ b/src/qml/types/qqmlconnections.cpp
 | ||||||
|  | @@ -338,7 +338,7 @@ void QQmlConnections::connectSignalsToMethods()
 | ||||||
|  |                     && propName.at(2).isUpper()) { | ||||||
|  |              qmlWarning(this) << tr("Detected function \"%1\" in Connections element. " | ||||||
|  |                                     "This is probably intended to be a signal handler but no " | ||||||
|  | -                                   "signal of the target matches the name.").arg(propName);
 | ||||||
|  | +                                   "signal of the \"%2\" target matches the name.").arg(propName).arg(target->metaObject()->className());
 | ||||||
|  |          } | ||||||
|  |      } | ||||||
|  |  } | ||||||
|  | diff --git a/tests/auto/qml/qqmllanguage/data/Broken.qml b/tests/auto/qml/qqmllanguage/data/Broken.qml
 | ||||||
|  | new file mode 100644 | ||||||
|  | index 0000000000..e24d9112a8
 | ||||||
|  | --- /dev/null
 | ||||||
|  | +++ b/tests/auto/qml/qqmllanguage/data/Broken.qml
 | ||||||
|  | @@ -0,0 +1,5 @@
 | ||||||
|  | +import QtQml 2.15
 | ||||||
|  | +
 | ||||||
|  | +QtObject {
 | ||||||
|  | +    notThere: 5
 | ||||||
|  | +}
 | ||||||
|  | diff --git a/tests/auto/qml/qqmllanguage/data/asBroken.qml b/tests/auto/qml/qqmllanguage/data/asBroken.qml
 | ||||||
|  | new file mode 100644 | ||||||
|  | index 0000000000..bd88d14c76
 | ||||||
|  | --- /dev/null
 | ||||||
|  | +++ b/tests/auto/qml/qqmllanguage/data/asBroken.qml
 | ||||||
|  | @@ -0,0 +1,6 @@
 | ||||||
|  | +import QtQml 2.15
 | ||||||
|  | +
 | ||||||
|  | +QtObject {
 | ||||||
|  | +    id: self
 | ||||||
|  | +    property var selfAsBroken: self as Broken
 | ||||||
|  | +}
 | ||||||
|  | diff --git a/tests/auto/qml/qqmllanguage/tst_qqmllanguage.cpp b/tests/auto/qml/qqmllanguage/tst_qqmllanguage.cpp
 | ||||||
|  | index bffb62c59e..97cc64991f 100644
 | ||||||
|  | --- a/tests/auto/qml/qqmllanguage/tst_qqmllanguage.cpp
 | ||||||
|  | +++ b/tests/auto/qml/qqmllanguage/tst_qqmllanguage.cpp
 | ||||||
|  | @@ -336,6 +336,7 @@ private slots:
 | ||||||
|  |      void bareInlineComponent(); | ||||||
|  |   | ||||||
|  |      void hangOnWarning(); | ||||||
|  | +    void objectAsBroken();
 | ||||||
|  |   | ||||||
|  |      void ambiguousContainingType(); | ||||||
|  |   | ||||||
|  | @@ -5876,6 +5877,21 @@ void tst_qqmllanguage::ambiguousContainingType()
 | ||||||
|  |      } | ||||||
|  |  } | ||||||
|  |   | ||||||
|  | +void tst_qqmllanguage::objectAsBroken()
 | ||||||
|  | +{
 | ||||||
|  | +    QQmlEngine engine;
 | ||||||
|  | +    QQmlComponent c(&engine, testFileUrl("asBroken.qml"));
 | ||||||
|  | +    QVERIFY2(c.isReady(), qPrintable(c.errorString()));
 | ||||||
|  | +    QScopedPointer<QObject> o(c.create());
 | ||||||
|  | +    QVERIFY(!o.isNull());
 | ||||||
|  | +    QVariant selfAsBroken = o->property("selfAsBroken");
 | ||||||
|  | +    QVERIFY(selfAsBroken.isValid());
 | ||||||
|  | +    // QCOMPARE(selfAsBroken.metaType(), QMetaType::fromType<std::nullptr_t>());
 | ||||||
|  | +
 | ||||||
|  | +    QQmlComponent b(&engine, testFileUrl("Broken.qml"));
 | ||||||
|  | +    QVERIFY(b.isError());
 | ||||||
|  | +}
 | ||||||
|  | +
 | ||||||
|  |  QTEST_MAIN(tst_qqmllanguage) | ||||||
|  |   | ||||||
|  |  #include "tst_qqmllanguage.moc" | ||||||
|  | -- 
 | ||||||
|  | 2.40.0 | ||||||
|  | 
 | ||||||
							
								
								
									
										54
									
								
								0015-Fix-missing-glyphs-when-using-NativeRendering.patch
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										54
									
								
								0015-Fix-missing-glyphs-when-using-NativeRendering.patch
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,54 @@ | |||||||
|  | From d54b978c0cba2bf75e145c9e1b00d2a9ab495d70 Mon Sep 17 00:00:00 2001 | ||||||
|  | From: Eskil Abrahamsen Blomfeldt <eskil.abrahamsen-blomfeldt@qt.io> | ||||||
|  | Date: Mon, 19 Dec 2022 10:05:33 +0100 | ||||||
|  | Subject: [PATCH 15/19] Fix missing glyphs when using NativeRendering | ||||||
|  | 
 | ||||||
|  | When we look up glyphs with subpixel positions in the glyph cache, | ||||||
|  | we use the calculated subpixel position (from a set of predefined | ||||||
|  | subpixel positions) as key. In some very rare cases, we could end | ||||||
|  | up with different subpixel positions when looking up an on-screen | ||||||
|  | position than when we entered it into the cache, due to numerical | ||||||
|  | differences when doing the calculation.
 | ||||||
|  | 
 | ||||||
|  | The reason for this was that when entering the glyph into the | ||||||
|  | cache, we used the 16.6 fixed point representation, whereas when | ||||||
|  | looking up, we used the unmodified float. In some cases, the | ||||||
|  | converted fixed point approximation might snap to a different | ||||||
|  | predefined subpixel position than the floating point equivalent. | ||||||
|  | 
 | ||||||
|  | To avoid this, we reuse the converted fixed point positions when | ||||||
|  | looking up the glyphs in the cache. | ||||||
|  | 
 | ||||||
|  | [ChangeLog][Text] Fixed an issue where text using NativeRendering | ||||||
|  | would sometimes be missing glyphs. | ||||||
|  | 
 | ||||||
|  | Pick-to: 5.15 6.2 6.4 6.5 | ||||||
|  | Fixes: QTBUG-108713 | ||||||
|  | Change-Id: Iecc264eb3d27e875c24257eaefcfb18a1a5fb5be | ||||||
|  | Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org> | ||||||
|  | Reviewed-by: Lars Knoll <lars@knoll.priv.no> | ||||||
|  | (cherry picked from commit 4bad329985b75090c68a70cceee7edadc172d7ab) | ||||||
|  | ---
 | ||||||
|  |  src/quick/scenegraph/qsgdefaultglyphnode_p.cpp | 4 +++- | ||||||
|  |  1 file changed, 3 insertions(+), 1 deletion(-) | ||||||
|  | 
 | ||||||
|  | diff --git a/src/quick/scenegraph/qsgdefaultglyphnode_p.cpp b/src/quick/scenegraph/qsgdefaultglyphnode_p.cpp
 | ||||||
|  | index f912da5799..fd128aa06e 100644
 | ||||||
|  | --- a/src/quick/scenegraph/qsgdefaultglyphnode_p.cpp
 | ||||||
|  | +++ b/src/quick/scenegraph/qsgdefaultglyphnode_p.cpp
 | ||||||
|  | @@ -839,9 +839,11 @@ void QSGTextMaskMaterial::populate(const QPointF &p,
 | ||||||
|  |      bool supportsSubPixelPositions = fontD->fontEngine->supportsSubPixelPositions(); | ||||||
|  |      for (int i=0; i<glyphIndexes.size(); ++i) { | ||||||
|  |           QPointF glyphPosition = glyphPositions.at(i) + position; | ||||||
|  | +         QFixedPoint fixedPointPosition = fixedPointPositions.at(i);
 | ||||||
|  | +
 | ||||||
|  |           QFixed subPixelPosition; | ||||||
|  |           if (supportsSubPixelPositions) | ||||||
|  | -             subPixelPosition = fontD->fontEngine->subPixelPositionForX(QFixed::fromReal(glyphPosition.x()));
 | ||||||
|  | +             subPixelPosition = fontD->fontEngine->subPixelPositionForX(QFixed::fromReal(fixedPointPosition.x.toReal() * glyphCacheScaleX));
 | ||||||
|  |   | ||||||
|  |           QTextureGlyphCache::GlyphAndSubPixelPosition glyph(glyphIndexes.at(i), subPixelPosition); | ||||||
|  |           const QTextureGlyphCache::Coord &c = cache->coords.value(glyph); | ||||||
|  | -- 
 | ||||||
|  | 2.40.0 | ||||||
|  | 
 | ||||||
| @ -0,0 +1,32 @@ | |||||||
|  | From 70b44dd18b9727e9aae857297265a751700a297e Mon Sep 17 00:00:00 2001 | ||||||
|  | From: Fushan Wen <qydwhotmail@gmail.com> | ||||||
|  | Date: Tue, 10 Jan 2023 20:42:04 +0800 | ||||||
|  | Subject: [PATCH 16/19] Revert "Fix missing glyphs when using NativeRendering" | ||||||
|  | 
 | ||||||
|  | This reverts commit da5e53b649f50cd9cdd89dadbba16f05e4070be2. | ||||||
|  | 
 | ||||||
|  | It breaks fonts on Wayland when global scale > 100%. | ||||||
|  | ---
 | ||||||
|  |  src/quick/scenegraph/qsgdefaultglyphnode_p.cpp | 4 +--- | ||||||
|  |  1 file changed, 1 insertion(+), 3 deletions(-) | ||||||
|  | 
 | ||||||
|  | diff --git a/src/quick/scenegraph/qsgdefaultglyphnode_p.cpp b/src/quick/scenegraph/qsgdefaultglyphnode_p.cpp
 | ||||||
|  | index fd128aa06e..f912da5799 100644
 | ||||||
|  | --- a/src/quick/scenegraph/qsgdefaultglyphnode_p.cpp
 | ||||||
|  | +++ b/src/quick/scenegraph/qsgdefaultglyphnode_p.cpp
 | ||||||
|  | @@ -839,11 +839,9 @@ void QSGTextMaskMaterial::populate(const QPointF &p,
 | ||||||
|  |      bool supportsSubPixelPositions = fontD->fontEngine->supportsSubPixelPositions(); | ||||||
|  |      for (int i=0; i<glyphIndexes.size(); ++i) { | ||||||
|  |           QPointF glyphPosition = glyphPositions.at(i) + position; | ||||||
|  | -         QFixedPoint fixedPointPosition = fixedPointPositions.at(i);
 | ||||||
|  | -
 | ||||||
|  |           QFixed subPixelPosition; | ||||||
|  |           if (supportsSubPixelPositions) | ||||||
|  | -             subPixelPosition = fontD->fontEngine->subPixelPositionForX(QFixed::fromReal(fixedPointPosition.x.toReal() * glyphCacheScaleX));
 | ||||||
|  | +             subPixelPosition = fontD->fontEngine->subPixelPositionForX(QFixed::fromReal(glyphPosition.x()));
 | ||||||
|  |   | ||||||
|  |           QTextureGlyphCache::GlyphAndSubPixelPosition glyph(glyphIndexes.at(i), subPixelPosition); | ||||||
|  |           const QTextureGlyphCache::Coord &c = cache->coords.value(glyph); | ||||||
|  | -- 
 | ||||||
|  | 2.40.0 | ||||||
|  | 
 | ||||||
| @ -0,0 +1,57 @@ | |||||||
|  | From c1e41d061329cc886a56477c8c2fd0e81add7780 Mon Sep 17 00:00:00 2001 | ||||||
|  | From: Jaeyoon Jung <jaeyoon.jung@lge.com> | ||||||
|  | Date: Fri, 19 Feb 2021 08:11:57 +0900 | ||||||
|  | Subject: [PATCH 17/19] QQmlImportDatabase: Make sure the newly added import | ||||||
|  |  path be first | ||||||
|  | 
 | ||||||
|  | If it already exists in the import list, move it to the first place. | ||||||
|  | This is as per the description of QQmlEngine::addImportPath: | ||||||
|  | | The newly added path will be first in the importPathList(). | ||||||
|  | 
 | ||||||
|  | Change-Id: I782d355c46ada2a46cff72e63326208f39028e01 | ||||||
|  | Reviewed-by: Ulf Hermann <ulf.hermann@qt.io> | ||||||
|  | (cherry picked from commit 3e413803c698d21f398daf0450c8f501204eb167) | ||||||
|  | ---
 | ||||||
|  |  src/qml/qml/qqmlimport.cpp                   | 9 ++++++--- | ||||||
|  |  tests/auto/qml/qqmlimport/tst_qqmlimport.cpp | 5 +++++ | ||||||
|  |  2 files changed, 11 insertions(+), 3 deletions(-) | ||||||
|  | 
 | ||||||
|  | diff --git a/src/qml/qml/qqmlimport.cpp b/src/qml/qml/qqmlimport.cpp
 | ||||||
|  | index 10c6c41338..39bfcdc999 100644
 | ||||||
|  | --- a/src/qml/qml/qqmlimport.cpp
 | ||||||
|  | +++ b/src/qml/qml/qqmlimport.cpp
 | ||||||
|  | @@ -2120,9 +2120,12 @@ void QQmlImportDatabase::addImportPath(const QString& path)
 | ||||||
|  |          cPath.replace(Backslash, Slash); | ||||||
|  |      } | ||||||
|  |   | ||||||
|  | -    if (!cPath.isEmpty()
 | ||||||
|  | -        && !fileImportPath.contains(cPath))
 | ||||||
|  | -        fileImportPath.prepend(cPath);
 | ||||||
|  | +    if (!cPath.isEmpty()) {
 | ||||||
|  | +        if (fileImportPath.contains(cPath))
 | ||||||
|  | +            fileImportPath.move(fileImportPath.indexOf(cPath), 0);
 | ||||||
|  | +        else
 | ||||||
|  | +            fileImportPath.prepend(cPath);
 | ||||||
|  | +    }
 | ||||||
|  |  } | ||||||
|  |   | ||||||
|  |  /*! | ||||||
|  | diff --git a/tests/auto/qml/qqmlimport/tst_qqmlimport.cpp b/tests/auto/qml/qqmlimport/tst_qqmlimport.cpp
 | ||||||
|  | index 9c865b3f73..1f788f7a7f 100644
 | ||||||
|  | --- a/tests/auto/qml/qqmlimport/tst_qqmlimport.cpp
 | ||||||
|  | +++ b/tests/auto/qml/qqmlimport/tst_qqmlimport.cpp
 | ||||||
|  | @@ -154,6 +154,11 @@ void tst_QQmlImport::importPathOrder()
 | ||||||
|  |      engine.addImportPath(QT_QMLTEST_DATADIR); | ||||||
|  |      expectedImportPaths.prepend(QT_QMLTEST_DATADIR); | ||||||
|  |      QCOMPARE(expectedImportPaths, engine.importPathList()); | ||||||
|  | +
 | ||||||
|  | +    // Add qml2Imports again to make it the first of the list
 | ||||||
|  | +    engine.addImportPath(qml2Imports);
 | ||||||
|  | +    expectedImportPaths.move(expectedImportPaths.indexOf(qml2Imports), 0);
 | ||||||
|  | +    QCOMPARE(expectedImportPaths, engine.importPathList());
 | ||||||
|  |  } | ||||||
|  |   | ||||||
|  |  Q_DECLARE_METATYPE(QQmlImports::ImportVersion) | ||||||
|  | -- 
 | ||||||
|  | 2.40.0 | ||||||
|  | 
 | ||||||
							
								
								
									
										102
									
								
								0018-QQuickState-when-handle-QJSValue-properties-correctl.patch
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										102
									
								
								0018-QQuickState-when-handle-QJSValue-properties-correctl.patch
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,102 @@ | |||||||
|  | From 0e1bed3c3e27d44d86d6f68a8b93b96a4821575c Mon Sep 17 00:00:00 2001 | ||||||
|  | From: Fabian Kosmale <fabian.kosmale@qt.io> | ||||||
|  | Date: Wed, 20 Jul 2022 11:44:43 +0200 | ||||||
|  | Subject: [PATCH 18/19] QQuickState::when: handle QJSValue properties correctly | ||||||
|  | 
 | ||||||
|  | If one assigns a binding whose evaluation results in a QJSValue, care | ||||||
|  | must be take to correctly convert it into a bool. Instead of directly | ||||||
|  | using QVariant::value<bool>, one needs to first extract the QJSValue, | ||||||
|  | and only convert it to bool afterwards. | ||||||
|  | This is necessary due to the custom binding evaluation we're doing to | ||||||
|  | avoid state oscillation. | ||||||
|  | Amends a8c729d83979fb0b9939044d246e73b1d578e65b. | ||||||
|  | 
 | ||||||
|  | Fixes: QTBUG-105000 | ||||||
|  | Pick-to: 6.4 6.3 6.2 5.15 | ||||||
|  | Change-Id: I4b093b48edecf9e0f09d2b54d10c2ff527f24ac3 | ||||||
|  | Reviewed-by: Ulf Hermann <ulf.hermann@qt.io> | ||||||
|  | (cherry picked from commit 2c31d25a44b1221c151681e1bb68ef78618e0166) | ||||||
|  | ---
 | ||||||
|  |  src/quick/util/qquickstategroup.cpp            | 10 ++++++++-- | ||||||
|  |  .../quick/qquickstates/data/jsValueWhen.qml    | 18 ++++++++++++++++++ | ||||||
|  |  .../quick/qquickstates/tst_qquickstates.cpp    | 11 +++++++++++ | ||||||
|  |  3 files changed, 37 insertions(+), 2 deletions(-) | ||||||
|  |  create mode 100644 tests/auto/quick/qquickstates/data/jsValueWhen.qml | ||||||
|  | 
 | ||||||
|  | diff --git a/src/quick/util/qquickstategroup.cpp b/src/quick/util/qquickstategroup.cpp
 | ||||||
|  | index 7cb3138618..f732b1eb4a 100644
 | ||||||
|  | --- a/src/quick/util/qquickstategroup.cpp
 | ||||||
|  | +++ b/src/quick/util/qquickstategroup.cpp
 | ||||||
|  | @@ -381,8 +381,14 @@ bool QQuickStateGroupPrivate::updateAutoState()
 | ||||||
|  |                  const auto potentialWhenBinding = QQmlPropertyPrivate::binding(whenProp); | ||||||
|  |                  // if there is a binding, the value in when might not be up-to-date at this point | ||||||
|  |                  // so we manually reevaluate the binding | ||||||
|  | -                if (auto abstractBinding = dynamic_cast<QQmlBinding *>(potentialWhenBinding))
 | ||||||
|  | -                    whenValue = abstractBinding->evaluate().toBool();
 | ||||||
|  | +                if (auto abstractBinding = dynamic_cast<QQmlBinding *>(potentialWhenBinding)) {
 | ||||||
|  | +                    QVariant evalResult = abstractBinding->evaluate();
 | ||||||
|  | +                    if (evalResult.userType() == qMetaTypeId<QJSValue>())
 | ||||||
|  | +                        whenValue = evalResult.value<QJSValue>().toBool();
 | ||||||
|  | +                    else
 | ||||||
|  | +                        whenValue = evalResult.toBool();
 | ||||||
|  | +                }
 | ||||||
|  | +
 | ||||||
|  |                  if (whenValue) { | ||||||
|  |                      if (stateChangeDebug()) | ||||||
|  |                          qWarning() << "Setting auto state due to expression"; | ||||||
|  | diff --git a/tests/auto/quick/qquickstates/data/jsValueWhen.qml b/tests/auto/quick/qquickstates/data/jsValueWhen.qml
 | ||||||
|  | new file mode 100644 | ||||||
|  | index 0000000000..6d5eb1600c
 | ||||||
|  | --- /dev/null
 | ||||||
|  | +++ b/tests/auto/quick/qquickstates/data/jsValueWhen.qml
 | ||||||
|  | @@ -0,0 +1,18 @@
 | ||||||
|  | +import QtQuick 2.15
 | ||||||
|  | +
 | ||||||
|  | +Item {
 | ||||||
|  | +    id: root
 | ||||||
|  | +    property var prop: null
 | ||||||
|  | +    property bool works: false
 | ||||||
|  | +    states: [
 | ||||||
|  | +        State {
 | ||||||
|  | +            name: "mystate"
 | ||||||
|  | +            when: root.prop
 | ||||||
|  | +            PropertyChanges {
 | ||||||
|  | +                target: root
 | ||||||
|  | +                works: "works"
 | ||||||
|  | +            }
 | ||||||
|  | +        }
 | ||||||
|  | +    ]
 | ||||||
|  | +    Component.onCompleted: root.prop = new Object
 | ||||||
|  | +}
 | ||||||
|  | diff --git a/tests/auto/quick/qquickstates/tst_qquickstates.cpp b/tests/auto/quick/qquickstates/tst_qquickstates.cpp
 | ||||||
|  | index aa55b42935..26e86672b0 100644
 | ||||||
|  | --- a/tests/auto/quick/qquickstates/tst_qquickstates.cpp
 | ||||||
|  | +++ b/tests/auto/quick/qquickstates/tst_qquickstates.cpp
 | ||||||
|  | @@ -188,6 +188,7 @@ private slots:
 | ||||||
|  |      void revertListMemoryLeak(); | ||||||
|  |      void duplicateStateName(); | ||||||
|  |      void trivialWhen(); | ||||||
|  | +    void jsValueWhen();
 | ||||||
|  |      void noStateOsciallation(); | ||||||
|  |      void parentChangeCorrectReversal(); | ||||||
|  |      void revertNullObjectBinding(); | ||||||
|  | @@ -1734,6 +1735,16 @@ void tst_qquickstates::trivialWhen()
 | ||||||
|  |      QVERIFY(c.create()); | ||||||
|  |  } | ||||||
|  |   | ||||||
|  | +void tst_qquickstates::jsValueWhen()
 | ||||||
|  | +{
 | ||||||
|  | +    QQmlEngine engine;
 | ||||||
|  | +
 | ||||||
|  | +    QQmlComponent c(&engine, testFileUrl("jsValueWhen.qml"));
 | ||||||
|  | +    QScopedPointer<QObject> root(c.create());
 | ||||||
|  | +    QVERIFY(root);
 | ||||||
|  | +    QVERIFY(root->property("works").toBool());
 | ||||||
|  | +}
 | ||||||
|  | +
 | ||||||
|  |  void tst_qquickstates::noStateOsciallation() | ||||||
|  |  { | ||||||
|  |     QQmlEngine engine; | ||||||
|  | -- 
 | ||||||
|  | 2.40.0 | ||||||
|  | 
 | ||||||
							
								
								
									
										162
									
								
								0019-Models-Avoid-crashes-when-deleting-cache-items.patch
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										162
									
								
								0019-Models-Avoid-crashes-when-deleting-cache-items.patch
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,162 @@ | |||||||
|  | From 89bf481b9b14f038c5e16421a7fce6dc6523785f Mon Sep 17 00:00:00 2001 | ||||||
|  | From: Ulf Hermann <ulf.hermann@qt.io> | ||||||
|  | Date: Wed, 29 Mar 2023 16:36:03 +0200 | ||||||
|  | Subject: [PATCH 19/19] Models: Avoid crashes when deleting cache items | ||||||
|  | 
 | ||||||
|  | Pick-to: 6.5 6.2 5.15 | ||||||
|  | Fixes: QTBUG-91425 | ||||||
|  | Change-Id: I58cf9ee29922f83fc6621f771b80ed557b31f106 | ||||||
|  | Reviewed-by: Shawn Rutledge <shawn.rutledge@qt.io> | ||||||
|  | Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io> | ||||||
|  | (cherry picked from commit 0cfdecba54e4f40468c4c9a8a6668cc1bc0eff65) | ||||||
|  | 
 | ||||||
|  | * asturmlechner 2023-04-08: Resolve conflict with dev branch commit | ||||||
|  |   c2d490a2385ea6f389340a296acaac0fa198c8b9 (qAsConst to std::as_const) | ||||||
|  | ---
 | ||||||
|  |  src/qmlmodels/qqmldelegatemodel.cpp           | 23 ++++++--- | ||||||
|  |  .../qml/qqmldelegatemodel/data/deleteRace.qml | 50 +++++++++++++++++++ | ||||||
|  |  .../tst_qqmldelegatemodel.cpp                 | 12 +++++ | ||||||
|  |  3 files changed, 78 insertions(+), 7 deletions(-) | ||||||
|  |  create mode 100644 tests/auto/qml/qqmldelegatemodel/data/deleteRace.qml | ||||||
|  | 
 | ||||||
|  | diff --git a/src/qmlmodels/qqmldelegatemodel.cpp b/src/qmlmodels/qqmldelegatemodel.cpp
 | ||||||
|  | index bc6b2447af..551e0ede95 100644
 | ||||||
|  | --- a/src/qmlmodels/qqmldelegatemodel.cpp
 | ||||||
|  | +++ b/src/qmlmodels/qqmldelegatemodel.cpp
 | ||||||
|  | @@ -1883,10 +1883,15 @@ void QQmlDelegateModelPrivate::emitChanges()
 | ||||||
|  |      for (int i = 1; i < m_groupCount; ++i) | ||||||
|  |          QQmlDelegateModelGroupPrivate::get(m_groups[i])->emitModelUpdated(reset); | ||||||
|  |   | ||||||
|  | -    auto cacheCopy = m_cache; // deliberate; emitChanges may alter m_cache
 | ||||||
|  | -    for (QQmlDelegateModelItem *cacheItem : qAsConst(cacheCopy)) {
 | ||||||
|  | -        if (cacheItem->attached)
 | ||||||
|  | -            cacheItem->attached->emitChanges();
 | ||||||
|  | +    // emitChanges may alter m_cache and delete items
 | ||||||
|  | +    QVarLengthArray<QPointer<QQmlDelegateModelAttached>> attachedObjects;
 | ||||||
|  | +    attachedObjects.reserve(m_cache.length());
 | ||||||
|  | +    for (const QQmlDelegateModelItem *cacheItem : qAsConst(m_cache))
 | ||||||
|  | +        attachedObjects.append(cacheItem->attached);
 | ||||||
|  | +
 | ||||||
|  | +    for (const QPointer<QQmlDelegateModelAttached> &attached : qAsConst(attachedObjects)) {
 | ||||||
|  | +        if (attached && attached->m_cacheItem)
 | ||||||
|  | +            attached->emitChanges();
 | ||||||
|  |      } | ||||||
|  |  } | ||||||
|  |   | ||||||
|  | @@ -2707,20 +2712,24 @@ void QQmlDelegateModelAttached::emitChanges()
 | ||||||
|  |      m_previousGroups = m_cacheItem->groups; | ||||||
|  |   | ||||||
|  |      int indexChanges = 0; | ||||||
|  | -    for (int i = 1; i < m_cacheItem->metaType->groupCount; ++i) {
 | ||||||
|  | +    const int groupCount = m_cacheItem->metaType->groupCount;
 | ||||||
|  | +    for (int i = 1; i < groupCount; ++i) {
 | ||||||
|  |          if (m_previousIndex[i] != m_currentIndex[i]) { | ||||||
|  |              m_previousIndex[i] = m_currentIndex[i]; | ||||||
|  |              indexChanges |= (1 << i); | ||||||
|  |          } | ||||||
|  |      } | ||||||
|  |   | ||||||
|  | +    // Don't access m_cacheItem anymore once we've started sending signals.
 | ||||||
|  | +    // We don't own it and someone might delete it.
 | ||||||
|  | +
 | ||||||
|  |      int notifierId = 0; | ||||||
|  |      const QMetaObject *meta = metaObject(); | ||||||
|  | -    for (int i = 1; i < m_cacheItem->metaType->groupCount; ++i, ++notifierId) {
 | ||||||
|  | +    for (int i = 1; i < groupCount; ++i, ++notifierId) {
 | ||||||
|  |          if (groupChanges & (1 << i)) | ||||||
|  |              QMetaObject::activate(this, meta, notifierId, nullptr); | ||||||
|  |      } | ||||||
|  | -    for (int i = 1; i < m_cacheItem->metaType->groupCount; ++i, ++notifierId) {
 | ||||||
|  | +    for (int i = 1; i < groupCount; ++i, ++notifierId) {
 | ||||||
|  |          if (indexChanges & (1 << i)) | ||||||
|  |              QMetaObject::activate(this, meta, notifierId, nullptr); | ||||||
|  |      } | ||||||
|  | diff --git a/tests/auto/qml/qqmldelegatemodel/data/deleteRace.qml b/tests/auto/qml/qqmldelegatemodel/data/deleteRace.qml
 | ||||||
|  | new file mode 100644 | ||||||
|  | index 0000000000..23874970e7
 | ||||||
|  | --- /dev/null
 | ||||||
|  | +++ b/tests/auto/qml/qqmldelegatemodel/data/deleteRace.qml
 | ||||||
|  | @@ -0,0 +1,50 @@
 | ||||||
|  | +import QtQuick 2.15
 | ||||||
|  | +import QtQml.Models 2.15
 | ||||||
|  | +
 | ||||||
|  | +Item {
 | ||||||
|  | +    DelegateModel {
 | ||||||
|  | +        id: delegateModel
 | ||||||
|  | +        model: ListModel {
 | ||||||
|  | +            id: sourceModel
 | ||||||
|  | +
 | ||||||
|  | +            ListElement { title: "foo" }
 | ||||||
|  | +            ListElement { title: "bar" }
 | ||||||
|  | +
 | ||||||
|  | +            function clear() {
 | ||||||
|  | +                if (count > 0)
 | ||||||
|  | +                    remove(0, count);
 | ||||||
|  | +            }
 | ||||||
|  | +        }
 | ||||||
|  | +
 | ||||||
|  | +        groups: [
 | ||||||
|  | +            DelegateModelGroup { name: "selectedItems" }
 | ||||||
|  | +        ]
 | ||||||
|  | +
 | ||||||
|  | +        delegate: Text {
 | ||||||
|  | +            height: DelegateModel.inSelectedItems ? implicitHeight * 2 : implicitHeight
 | ||||||
|  | +            Component.onCompleted: {
 | ||||||
|  | +                if (index === 0)
 | ||||||
|  | +                    DelegateModel.inSelectedItems = true;
 | ||||||
|  | +            }
 | ||||||
|  | +        }
 | ||||||
|  | +
 | ||||||
|  | +        Component.onCompleted: {
 | ||||||
|  | +            items.create(0)
 | ||||||
|  | +            items.create(1)
 | ||||||
|  | +        }
 | ||||||
|  | +    }
 | ||||||
|  | +
 | ||||||
|  | +    ListView {
 | ||||||
|  | +        anchors.fill: parent
 | ||||||
|  | +        model: delegateModel
 | ||||||
|  | +    }
 | ||||||
|  | +
 | ||||||
|  | +    Timer {
 | ||||||
|  | +        running: true
 | ||||||
|  | +        interval: 10
 | ||||||
|  | +        onTriggered: sourceModel.clear()
 | ||||||
|  | +    }
 | ||||||
|  | +
 | ||||||
|  | +    property int count: delegateModel.items.count
 | ||||||
|  | +}
 | ||||||
|  | +
 | ||||||
|  | diff --git a/tests/auto/qml/qqmldelegatemodel/tst_qqmldelegatemodel.cpp b/tests/auto/qml/qqmldelegatemodel/tst_qqmldelegatemodel.cpp
 | ||||||
|  | index 1722447830..f473cff75f 100644
 | ||||||
|  | --- a/tests/auto/qml/qqmldelegatemodel/tst_qqmldelegatemodel.cpp
 | ||||||
|  | +++ b/tests/auto/qml/qqmldelegatemodel/tst_qqmldelegatemodel.cpp
 | ||||||
|  | @@ -50,6 +50,7 @@ private slots:
 | ||||||
|  |      void qtbug_86017(); | ||||||
|  |      void contextAccessedByHandler(); | ||||||
|  |      void redrawUponColumnChange(); | ||||||
|  | +    void deleteRace();
 | ||||||
|  |  }; | ||||||
|  |   | ||||||
|  |  class AbstractItemModel : public QAbstractItemModel | ||||||
|  | @@ -213,6 +214,17 @@ void tst_QQmlDelegateModel::redrawUponColumnChange()
 | ||||||
|  |      QCOMPARE(item->property("text").toString(), "Coconut"); | ||||||
|  |  } | ||||||
|  |   | ||||||
|  | +void tst_QQmlDelegateModel::deleteRace()
 | ||||||
|  | +{
 | ||||||
|  | +    QQmlEngine engine;
 | ||||||
|  | +    QQmlComponent c(&engine, testFileUrl("deleteRace.qml"));
 | ||||||
|  | +    QVERIFY2(c.isReady(), qPrintable(c.errorString()));
 | ||||||
|  | +    QScopedPointer<QObject> o(c.create());
 | ||||||
|  | +    QVERIFY(!o.isNull());
 | ||||||
|  | +    QTRY_COMPARE(o->property("count").toInt(), 2);
 | ||||||
|  | +    QTRY_COMPARE(o->property("count").toInt(), 0);
 | ||||||
|  | +}
 | ||||||
|  | +
 | ||||||
|  |  QTEST_MAIN(tst_QQmlDelegateModel) | ||||||
|  |   | ||||||
|  |  #include "tst_qqmldelegatemodel.moc" | ||||||
|  | -- 
 | ||||||
|  | 2.40.0 | ||||||
|  | 
 | ||||||
		Loading…
	
		Reference in New Issue
	
	Block a user