a11y: Prevent one case of losing a11y interface when setting event child
9a369a25dd added a
QAccessibleEvent ctor that takes a QAccessibleInterface*
instead of a QObject*.
Retrieving the QAccessibleInterface* later is done using the
interface's unique ID stored in the m_uniqueId member.
However, the fact that m_uniqueId is a member
of the union alongside with m_child means that setting
a child via QAccessibleEvent::setChild also overwrites
the stored unique ID, which breaks retrieving the accessible
interface later.
Fix this for the case where the QAccessibleInterface has
an associated QObject by assigning m_object in the ctor as well.
This means that a QAccessibleEvent created using either of the two
constructors (the one taking the QObject* and the one taking
the QAccessibleInterface* associated with the object) now behaves
the same.
Fixing the case where there is no associated QObject would require
further changes (e.g. adding a member for the QAccessibleInterface*
or making the m_uniqueId member a separate member instead of having
it in a union with m_child). However, I see no way to do so without
breaking the ABI, so that is left unchanged.
This also adds a corresponding test case.
Fixes: QTBUG-105988
Pick-to: 6.4
Change-Id: I71a548af0277a5034e9e207f066fa3e25c5393f3
Reviewed-by: Tor Arne Vestbø <tor.arne.vestbo@qt.io>
bb10
parent
063344c8b9
commit
0c0eadc484
|
|
@ -287,7 +287,7 @@ public:
|
|||
}
|
||||
|
||||
inline QAccessibleEvent(QAccessibleInterface *iface, QAccessible::Event typ)
|
||||
: m_type(typ), m_object(nullptr)
|
||||
: m_type(typ)
|
||||
{
|
||||
Q_ASSERT(iface);
|
||||
Q_ASSERT(m_type != QAccessible::ValueChanged);
|
||||
|
|
@ -299,6 +299,7 @@ public:
|
|||
Q_ASSERT(m_type != QAccessible::TextUpdated);
|
||||
Q_ASSERT(m_type != QAccessible::TableModelChanged);
|
||||
m_uniqueId = QAccessible::uniqueId(iface);
|
||||
m_object = iface->object();
|
||||
}
|
||||
|
||||
virtual ~QAccessibleEvent();
|
||||
|
|
|
|||
|
|
@ -163,6 +163,7 @@ public slots:
|
|||
void cleanup();
|
||||
private slots:
|
||||
void eventTest();
|
||||
void eventWithChildTest();
|
||||
void customWidget();
|
||||
void deletedWidget();
|
||||
void subclassedWidget();
|
||||
|
|
@ -353,6 +354,33 @@ void tst_QAccessibility::eventTest()
|
|||
QTestAccessibility::clearEvents();
|
||||
}
|
||||
|
||||
void tst_QAccessibility::eventWithChildTest()
|
||||
{
|
||||
// make sure that QAccessibleEvent created using either of the two QAccessibleEvent
|
||||
// behaves the same when the same underlying QObject is used
|
||||
QWidget widget;
|
||||
QWidget childWidget(&widget);
|
||||
|
||||
// QAccessibleEvent constructor called with the QObject*
|
||||
QAccessibleEvent event1(&widget, QAccessible::Focus);
|
||||
|
||||
// QAccessibleEvent constructor called with the QAccessibleInterface* for the same QObject*
|
||||
QAccessibleInterface *iface = QAccessible::queryAccessibleInterface(&widget);
|
||||
QAccessibleEvent event2(iface, QAccessible::Focus);
|
||||
|
||||
QVERIFY(event1.accessibleInterface() != nullptr);
|
||||
QVERIFY(event2.accessibleInterface() != nullptr);
|
||||
QCOMPARE(event1.accessibleInterface(), event2.accessibleInterface());
|
||||
|
||||
// set same child for both
|
||||
event1.setChild(0);
|
||||
event2.setChild(0);
|
||||
|
||||
QVERIFY(event1.accessibleInterface() != nullptr);
|
||||
QVERIFY(event2.accessibleInterface() != nullptr);
|
||||
QCOMPARE(event1.accessibleInterface(), event2.accessibleInterface());
|
||||
}
|
||||
|
||||
void tst_QAccessibility::customWidget()
|
||||
{
|
||||
{
|
||||
|
|
|
|||
Loading…
Reference in New Issue