diff --git a/src/gui/accessible/qaccessiblecache.cpp b/src/gui/accessible/qaccessiblecache.cpp index d9586519c78..3010ffdd2b4 100644 --- a/src/gui/accessible/qaccessiblecache.cpp +++ b/src/gui/accessible/qaccessiblecache.cpp @@ -48,18 +48,18 @@ QAccessibleCache *QAccessibleCache::instance() QAccessible::Id QAccessibleCache::acquireId() const { static const QAccessible::Id FirstId = QAccessible::Id(INT_MAX) + 1; - static QAccessible::Id lastUsedId = FirstId; + static QAccessible::Id nextId = FirstId; - while (idToInterface.contains(lastUsedId)) { + while (idToInterface.contains(nextId)) { // (wrap back when when we reach UINT_MAX - 1) // -1 because on Android -1 is taken for the "View" so just avoid it completely for consistency - if (lastUsedId == UINT_MAX - 1) - lastUsedId = FirstId; + if (nextId == UINT_MAX - 1) + nextId = FirstId; else - ++lastUsedId; + ++nextId; } - return lastUsedId; + return nextId++; } QAccessibleInterface *QAccessibleCache::interfaceForId(QAccessible::Id id) const diff --git a/tests/auto/other/qaccessibility/tst_qaccessibility.cpp b/tests/auto/other/qaccessibility/tst_qaccessibility.cpp index 8479985c0e8..453f6b6fed2 100644 --- a/tests/auto/other/qaccessibility/tst_qaccessibility.cpp +++ b/tests/auto/other/qaccessibility/tst_qaccessibility.cpp @@ -211,6 +211,7 @@ private slots: void treeTest(); void tableTest(); + void uniqueIdTest(); void calendarWidgetTest(); void dockWidgetTest(); void comboBoxTest(); @@ -3385,6 +3386,25 @@ void tst_QAccessibility::tableTest() QTestAccessibility::clearEvents(); } +void tst_QAccessibility::uniqueIdTest() +{ + // Test that an ID isn't reassigned to another interface right away when an accessible interface + // that has just been created is removed from the cache and deleted before the next + // accessible interface is registered. + // For example for AT-SPI, that would result in the same object path being used, and thus + // data from the old and new interface can get confused due to caching. + QWidget widget1; + QAccessibleInterface *iface1 = QAccessible::queryAccessibleInterface(&widget1); + QAccessible::Id id1 = QAccessible::uniqueId(iface1); + QAccessible::deleteAccessibleInterface(id1); + + QWidget widget2; + QAccessibleInterface *iface2 = QAccessible::queryAccessibleInterface(&widget2); + QAccessible::Id id2 = QAccessible::uniqueId(iface2); + + QVERIFY(id1 != id2); +} + void tst_QAccessibility::calendarWidgetTest() { #if QT_CONFIG(calendarwidget)