From 02c2ad6cbea5b9c3e8da5a23bdbb402357dba0f0 Mon Sep 17 00:00:00 2001 From: Fabian Kosmale Date: Tue, 3 May 2022 08:53:38 +0200 Subject: Revert "a11y: Do not cache classes that don't have a factory plugin" This reverts commit 583668005d4d6399fc16d165dcb6a5af2b94323d, and provides an alternative fix for QTBUG-75106. Reason: This introduced QTBUG-103009, due to lack of caching. To fix the original issue, we still reduce the amount of caching we do, by only considering the first non-dynamic meta-object for QML related objects. Task-number: QTBUG-75106 Fixes: QTBUG-103009 Pick-to: 6.3 6.2 5.15 Change-Id: Ic76af26a719d1114208be9555286239c6c6df615 Reviewed-by: Volker Hilsheimer --- src/gui/accessible/qaccessible.cpp | 29 +++++++++++++++++++++++++---- 1 file changed, 25 insertions(+), 4 deletions(-) (limited to 'src/gui/accessible') diff --git a/src/gui/accessible/qaccessible.cpp b/src/gui/accessible/qaccessible.cpp index 30e5a32b1d..ee409bd179 100644 --- a/src/gui/accessible/qaccessible.cpp +++ b/src/gui/accessible/qaccessible.cpp @@ -54,6 +54,7 @@ #include #include #include +#include #include #include @@ -682,6 +683,25 @@ QAccessibleInterface *QAccessible::queryAccessibleInterface(QObject *object) // Create a QAccessibleInterface for the object class. Start by the most // derived class and walk up the class hierarchy. const QMetaObject *mo = object->metaObject(); + const auto *objectPriv = QObjectPrivate::get(object); + /* + We do not want to cache each and every QML metaobject (Button_QMLTYPE_124, + Button_QMLTYPE_125, etc.). Those dynamic metaobjects shouldn't have an + accessible interface in any case. Instead, we start the whole checking + with the first non-dynamic meta-object. To avoid potential regressions + in other areas of Qt that also use dynamic metaobjects, we only do this + for objects that are QML-related (approximated by checking whether they + have ddata set). + */ + const bool qmlRelated = !objectPriv->isDeletingChildren && + objectPriv->declarativeData; + while (qmlRelated && mo) { + auto mop = QMetaObjectPrivate::get(mo); + if (!mop || !(mop->flags & DynamicMetaObject)) + break; + + mo = mo->superClass(); + }; while (mo) { const QString cn = QLatin1StringView(mo->className()); @@ -697,14 +717,15 @@ QAccessibleInterface *QAccessible::queryAccessibleInterface(QObject *object) // Find a QAccessiblePlugin (factory) for the class name. If there's // no entry in the cache try to create it using the plugin loader. if (!qAccessiblePlugins()->contains(cn)) { + QAccessiblePlugin *factory = nullptr; // 0 means "no plugin found". This is cached as well. const int index = loader()->indexOf(cn); - if (index != -1) { - QAccessiblePlugin *factory = qobject_cast(loader()->instance(index)); - qAccessiblePlugins()->insert(cn, factory); - } + if (index != -1) + factory = qobject_cast(loader()->instance(index)); + qAccessiblePlugins()->insert(cn, factory); } // At this point the cache should contain a valid factory pointer or 0: + Q_ASSERT(qAccessiblePlugins()->contains(cn)); QAccessiblePlugin *factory = qAccessiblePlugins()->value(cn); if (factory) { QAccessibleInterface *result = factory->create(cn, object); -- cgit v1.2.3