Accessibility: don't emit focus change when reason is window activation

If a window becomes active, then the accessibility system gets informed
about that already. Qt puts focus on the focus child of the activated
window afterwards, and if this emits another accessibility event, then
accessibility clients like Windows Narrator will stop reading the
activated window, and instead read about the focused widget.

This makes dialogs like message boxes poorly accessible.

Accessibility clients already know that a window became active, and can
query Qt about the focused child within that window.

Amend test case.

Fixes: QTBUG-101585
Change-Id: I2d6bff7c415a6f29c4a4f7f4e4be38079fb976ca
Reviewed-by: Jan Arve Sæther <jan-arve.saether@qt.io>
(cherry picked from commit 79a11470f3c4c61951906223f97001a77ce36500)
Reviewed-by: Qt Cherry-pick Bot <cherrypick_bot@qt-project.org>
This commit is contained in:
Volker Hilsheimer 2022-06-15 12:32:23 +02:00 committed by Qt Cherry-pick Bot
parent bbde24f19a
commit ef75047a63
2 changed files with 19 additions and 5 deletions

View File

@ -6513,11 +6513,15 @@ void QWidget::setFocus(Qt::FocusReason reason)
QApplicationPrivate::setFocusWidget(f, reason);
#if QT_CONFIG(accessibility)
// menus update the focus manually and this would create bogus events
if (!(f->inherits("QMenuBar") || f->inherits("QMenu") || f->inherits("QMenuItem")))
{
QAccessibleEvent event(f, QAccessible::Focus);
QAccessible::updateAccessibility(&event);
// If the widget gets focus because its window becomes active, then the accessibility
// subsystem is already informed about the window opening, and also knows which child
// within the window has focus. Don't interrupt it by emitting another focus event.
if (reason != Qt::ActiveWindowFocusReason) {
// menus update the focus manually and this would create bogus events
if (!(f->inherits("QMenuBar") || f->inherits("QMenu") || f->inherits("QMenuItem"))) {
QAccessibleEvent event(f, QAccessible::Focus);
QAccessible::updateAccessibility(&event);
}
}
#endif
#if QT_CONFIG(graphicsview)

View File

@ -4288,10 +4288,20 @@ void tst_QAccessibility::messageBoxTest()
if (!boxPrivate->canBeNativeDialog()) {
// platforms that use a native message box will not emit accessibility events
box.show();
QVERIFY(QTest::qWaitForWindowActive(&box));
QAccessibleEvent showEvent(&box, QAccessible::DialogStart);
QVERIFY(QTestAccessibility::containsEvent(&showEvent));
// on some platforms, like macOS, not all widgets get key board focus; we
// only care about a push button getting focus
if (QTest::qWaitFor([&box]{ return qobject_cast<QPushButton *>(box.focusWidget()); }, 1000)) {
// a widget that gets focus through window activation should not emit an accessibility
// notification
QAccessibleEvent focusEvent(box.focusWidget(), QAccessible::Focus);
QVERIFY(!QTestAccessibility::containsEvent(&focusEvent));
}
box.hide();
QAccessibleEvent hideEvent(&box, QAccessible::DialogEnd);