a11y: reduce the number of activation observer calls
Reduce the number of activation calls by calling the observer callbacks on active state change only, instead of on each setActive() call. The accessibility backends typically make setActive() calls on each accessibility event, which can result in a large number (100k+) of activation calls if there are many (hundreds) of installed activation observers. This change keeps the following behavior compatibilities: - Each observer is called at least once on setActive(), even if the active state has not changed since it was installed. - Going from active to inactive is supported, though Qt currently does not appear to do this. As a drive-by refactor, make it possible to activate accessibility by calling QAccessible::setActive(), by making it call QPlatformAccessible::setActive(). Change-Id: Iee17160f153b825be032b441923e3529c2f00242 Reviewed-by: Tor Arne Vestbø <tor.arne.vestbo@qt.io>
This commit is contained in:
parent
e57fff6341
commit
51c7503568
@ -688,6 +688,11 @@ void QAccessible::installActivationObserver(QAccessible::ActivationObserver *obs
|
||||
if (qAccessibleActivationObservers()->contains(observer))
|
||||
return;
|
||||
qAccessibleActivationObservers()->append(observer);
|
||||
|
||||
// Make sure the newly added observer gets a callback on the next
|
||||
// QPlatformAccessibility::setActive() callback
|
||||
if (QPlatformAccessibility *pfAccessibility = platformAccessibility())
|
||||
pfAccessibility->clearActiveNotificationState();
|
||||
}
|
||||
|
||||
/*!
|
||||
@ -701,6 +706,17 @@ void QAccessible::removeActivationObserver(ActivationObserver *observer)
|
||||
qAccessibleActivationObservers()->removeAll(observer);
|
||||
}
|
||||
|
||||
/*!
|
||||
\internal
|
||||
|
||||
Sends accessibility activation notifications to all registered observers.
|
||||
*/
|
||||
void qAccessibleNotifyActivationObservers(bool active)
|
||||
{
|
||||
for (int i = 0; i < qAccessibleActivationObservers()->size(); ++i)
|
||||
qAccessibleActivationObservers()->at(i)->accessibilityActiveChanged(active);
|
||||
}
|
||||
|
||||
/*!
|
||||
If a QAccessibleInterface implementation exists for the given \a object,
|
||||
this function returns a pointer to the implementation; otherwise it
|
||||
@ -870,11 +886,10 @@ bool QAccessible::isActive()
|
||||
*/
|
||||
void QAccessible::setActive(bool active)
|
||||
{
|
||||
for (int i = 0; i < qAccessibleActivationObservers()->size() ;++i)
|
||||
qAccessibleActivationObservers()->at(i)->accessibilityActiveChanged(active);
|
||||
if (QPlatformAccessibility *pfAccessibility = platformAccessibility())
|
||||
pfAccessibility->setActive(active);
|
||||
}
|
||||
|
||||
|
||||
/*!
|
||||
Sets the root object of the accessible objects of this application
|
||||
to \a object. All other accessible objects are reachable using object
|
||||
|
@ -35,7 +35,6 @@ Q_GLOBAL_STATIC(QList<QAccessibleBridge *>, bridges)
|
||||
\sa QAccessible
|
||||
*/
|
||||
QPlatformAccessibility::QPlatformAccessibility()
|
||||
: m_active(false)
|
||||
{
|
||||
}
|
||||
|
||||
@ -99,10 +98,25 @@ void QPlatformAccessibility::cleanup()
|
||||
qDeleteAll(*bridges());
|
||||
}
|
||||
|
||||
void qAccessibleNotifyActivationObservers(bool active); // qaccessible.cpp
|
||||
|
||||
void QPlatformAccessibility::setActive(bool active)
|
||||
{
|
||||
m_active = active;
|
||||
QAccessible::setActive(active);
|
||||
|
||||
// Send activeChanged notifications if the new active status differs from
|
||||
// the notifed one.
|
||||
if ((active && m_activeNotificationState != std::optional<bool>{true}) ||
|
||||
(!active && m_activeNotificationState != std::optional<bool>{false})) {
|
||||
qAccessibleNotifyActivationObservers(active);
|
||||
}
|
||||
|
||||
m_activeNotificationState = active;
|
||||
}
|
||||
|
||||
void QPlatformAccessibility::clearActiveNotificationState()
|
||||
{
|
||||
m_activeNotificationState = std::nullopt;
|
||||
}
|
||||
|
||||
#endif // QT_CONFIG(accessibility)
|
||||
|
@ -19,6 +19,8 @@
|
||||
#include <QtCore/qobject.h>
|
||||
#include <QtGui/qaccessible.h>
|
||||
|
||||
#include <optional>
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
||||
|
||||
@ -35,9 +37,11 @@ public:
|
||||
|
||||
inline bool isActive() const { return m_active; }
|
||||
void setActive(bool active);
|
||||
void clearActiveNotificationState();
|
||||
|
||||
private:
|
||||
bool m_active;
|
||||
bool m_active = false;
|
||||
std::optional<bool> m_activeNotificationState = std::nullopt;
|
||||
};
|
||||
|
||||
QT_END_NAMESPACE
|
||||
|
Loading…
x
Reference in New Issue
Block a user