diff options
Diffstat (limited to 'src')
32 files changed, 1020 insertions, 638 deletions
diff --git a/src/gui/accessible/accessible.pri b/src/gui/accessible/accessible.pri index 592607bce5..6fdb2d35b2 100644 --- a/src/gui/accessible/accessible.pri +++ b/src/gui/accessible/accessible.pri @@ -3,6 +3,7 @@ contains(QT_CONFIG, accessibility) { HEADERS += \ accessible/qaccessible.h \ + accessible/qaccessiblecache_p.h \ accessible/qaccessible2_p.h \ accessible/qaccessibleobject.h \ accessible/qaccessibleplugin.h \ @@ -10,6 +11,7 @@ contains(QT_CONFIG, accessibility) { SOURCES += accessible/qaccessible.cpp \ accessible/qaccessible2.cpp \ + accessible/qaccessiblecache.cpp \ accessible/qaccessibleobject.cpp \ accessible/qaccessibleplugin.cpp \ accessible/qplatformaccessibility.cpp diff --git a/src/gui/accessible/qaccessible.cpp b/src/gui/accessible/qaccessible.cpp index 3468ebc8a7..e007c9967e 100644 --- a/src/gui/accessible/qaccessible.cpp +++ b/src/gui/accessible/qaccessible.cpp @@ -41,6 +41,8 @@ #include "qaccessible.h" +#include "qaccessible2_p.h" +#include "qaccessiblecache_p.h" #include "qaccessibleplugin.h" #include "qaccessibleobject.h" #include "qaccessiblebridge.h" @@ -558,6 +560,8 @@ QAccessible::RootObjectHandler QAccessible::installRootObjectHandler(RootObjectH return old; } +Q_GLOBAL_STATIC(QAccessibleCache, qAccessibleCache) + /*! If a QAccessibleInterface implementation exists for the given \a object, this function returns a pointer to the implementation; otherwise it @@ -574,8 +578,7 @@ QAccessible::RootObjectHandler QAccessible::installRootObjectHandler(RootObjectH function tries to find an implementation for the object's parent class, using the above strategy. - \warning The caller is responsible for deleting the returned - interface after use. + All interfaces are managed by an internal cache and should not be deleted. */ QAccessibleInterface *QAccessible::queryAccessibleInterface(QObject *object) { @@ -583,6 +586,9 @@ QAccessibleInterface *QAccessible::queryAccessibleInterface(QObject *object) if (!object) return 0; + if (Id id = qAccessibleCache->objectToId.value(object)) + return qAccessibleCache->interfaceForId(id); + // Create a QAccessibleInterface for the object class. Start by the most // derived class and walk up the class hierarchy. const QMetaObject *mo = object->metaObject(); @@ -592,8 +598,11 @@ QAccessibleInterface *QAccessible::queryAccessibleInterface(QObject *object) // Check if the class has a InterfaceFactory installed. for (int i = qAccessibleFactories()->count(); i > 0; --i) { InterfaceFactory factory = qAccessibleFactories()->at(i - 1); - if (QAccessibleInterface *iface = factory(cn, object)) + if (QAccessibleInterface *iface = factory(cn, object)) { + qAccessibleCache->insert(object, iface); + Q_ASSERT(qAccessibleCache->objectToId.contains(object)); return iface; + } } #ifndef QT_NO_ACCESSIBILITY #ifndef QT_NO_LIBRARY @@ -610,22 +619,84 @@ QAccessibleInterface *QAccessible::queryAccessibleInterface(QObject *object) // 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) - return factory->create(cn, object); + if (factory) { + QAccessibleInterface *result = factory->create(cn, object); + if (result) { // Need this condition because of QDesktopScreenWidget + qAccessibleCache->insert(object, result); + Q_ASSERT(qAccessibleCache->objectToId.contains(object)); + } + return result; + } #endif #endif mo = mo->superClass(); } #ifndef QT_NO_ACCESSIBILITY - if (object == qApp) - return new QAccessibleApplication; + if (object == qApp) { + QAccessibleInterface *appInterface = new QAccessibleApplication; + qAccessibleCache->insert(object, appInterface); + Q_ASSERT(qAccessibleCache->objectToId.contains(qApp)); + return appInterface; + } #endif return 0; } /*! + \internal + Required to ensure that manually created interfaces + are properly memory managed. + + Must only be called exactly once per interface. + This is implicitly called when calling queryAccessibleInterface, + so it's only required when re-implementing for example + the child function and returning the child after new-ing + a QAccessibleInterface subclass. + */ +QAccessible::Id QAccessible::registerAccessibleInterface(QAccessibleInterface *iface) +{ + Q_ASSERT(iface); + return qAccessibleCache->insert(iface->object(), iface); +} + +/*! + \internal + Removes the interface belonging to this id from the cache and + deletes it. The id becomes invalid an may be re-used by the + cache. +*/ +void QAccessible::deleteAccessibleInterface(Id id) +{ + qAccessibleCache->deleteInterface(id); +} + +/*! + \internal + Returns the unique ID for the accessibleInterface. +*/ +QAccessible::Id QAccessible::uniqueId(QAccessibleInterface *iface) +{ + Id id = qAccessibleCache->idToInterface.key(iface); + if (!id) + id = registerAccessibleInterface(iface); + return id; +} + +/*! + \internal + Returns the QAccessibleInterface belonging to the id. + + Returns 0 if the id is invalid. +*/ +QAccessibleInterface *QAccessible::accessibleInterface(Id id) +{ + return qAccessibleCache->idToInterface.value(id); +} + + +/*! Returns true if an accessibility implementation has been requested during the runtime of the application; otherwise returns false. @@ -687,15 +758,23 @@ void QAccessible::setRootObject(QObject *object) */ void QAccessible::updateAccessibility(QAccessibleEvent *event) { - if (updateHandler) { - updateHandler(event); + if (!isActive()) return; + +#ifndef QT_NO_ACCESSIBILITY + if (event->type() == QAccessible::TableModelChanged) { + Q_ASSERT(event->object()); + if (QAccessibleInterface *iface = QAccessible::queryAccessibleInterface(event->object())) { + if (iface->tableInterface()) + iface->tableInterface()->modelChange(static_cast<QAccessibleTableModelChangeEvent*>(event)); + } } - if (!isActive()) + if (updateHandler) { + updateHandler(event); return; + } -#ifndef QT_NO_ACCESSIBILITY if (QPlatformAccessibility *pfAccessibility = platformAccessibility()) pfAccessibility->notifyAccessibilityUpdate(event); #endif @@ -1028,6 +1107,10 @@ QColor QAccessibleInterface::backgroundColor() const return QColor(); } +QAccessibleInterface::~QAccessibleInterface() +{ +} + /*! \fn QAccessibleTextInterface *QAccessibleInterface::textInterface() \internal @@ -1362,7 +1445,6 @@ QAccessibleInterface *QAccessibleEvent::accessibleInterface() const if (m_child >= 0) { QAccessibleInterface *child = iface->child(m_child); if (child) { - delete iface; iface = child; } else { qWarning() << "Cannot creat accessible child interface for object: " << m_object << " index: " << m_child; diff --git a/src/gui/accessible/qaccessible.h b/src/gui/accessible/qaccessible.h index 09e259c1d0..8447f34154 100644 --- a/src/gui/accessible/qaccessible.h +++ b/src/gui/accessible/qaccessible.h @@ -45,6 +45,7 @@ #ifndef QACCESSIBLE_H #define QACCESSIBLE_H +#include <QtCore/qdebug.h> #include <QtCore/qglobal.h> #include <QtCore/qobject.h> #include <QtCore/qrect.h> @@ -58,7 +59,6 @@ QT_BEGIN_NAMESPACE - class QAccessibleInterface; class QAccessibleEvent; class QWindow; @@ -335,12 +335,20 @@ public: typedef void(*UpdateHandler)(QAccessibleEvent *event); typedef void(*RootObjectHandler)(QObject*); + typedef unsigned Id; + static void installFactory(InterfaceFactory); static void removeFactory(InterfaceFactory); static UpdateHandler installUpdateHandler(UpdateHandler); static RootObjectHandler installRootObjectHandler(RootObjectHandler); static QAccessibleInterface *queryAccessibleInterface(QObject *); + static Id uniqueId(QAccessibleInterface *iface); + static QAccessibleInterface *accessibleInterface(Id uniqueId); + static Id registerAccessibleInterface(QAccessibleInterface *iface); + static void deleteAccessibleInterface(Id uniqueId); + + #if QT_DEPRECATED_SINCE(5, 0) QT_DEPRECATED static inline void updateAccessibility(QObject *object, int child, Event reason); #endif @@ -360,6 +368,8 @@ private: it is not supposed to be instantiated. */ QAccessible() {} + + friend class QAccessibleCache; }; Q_GUI_EXPORT bool operator==(const QAccessible::State &first, const QAccessible::State &second); @@ -377,8 +387,10 @@ class QAccessibleTableCellInterface; class Q_GUI_EXPORT QAccessibleInterface { +protected: + virtual ~QAccessibleInterface(); + public: - virtual ~QAccessibleInterface() {} // check for valid pointers virtual bool isValid() const = 0; virtual QObject *object() const = 0; @@ -431,7 +443,9 @@ public: virtual void *interface_cast(QAccessible::InterfaceType) { return 0; } -private: + +protected: + friend class QAccessibleCache; }; class Q_GUI_EXPORT QAccessibleEvent diff --git a/src/gui/accessible/qaccessible2_p.h b/src/gui/accessible/qaccessible2_p.h index 169ca2b5e5..1a1eeea4ba 100644 --- a/src/gui/accessible/qaccessible2_p.h +++ b/src/gui/accessible/qaccessible2_p.h @@ -193,6 +193,8 @@ public: // Unselects one column, leaving other selected columns selected (if any). virtual bool unselectColumn(int column) = 0; + virtual void modelChange(QAccessibleTableModelChangeEvent *event) = 0; + protected: friend class QAbstractItemView; friend class QAbstractItemViewPrivate; diff --git a/src/gui/accessible/qaccessiblecache.cpp b/src/gui/accessible/qaccessiblecache.cpp new file mode 100644 index 0000000000..1b79c30b6c --- /dev/null +++ b/src/gui/accessible/qaccessiblecache.cpp @@ -0,0 +1,116 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the QtGui module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qaccessiblecache_p.h" + +QT_BEGIN_NAMESPACE + +/*! + \class QAccessibleCache + \internal + \brief Maintains a cache of accessible interfaces. +*/ + +/* + The ID is always in the range [INT_MAX+1, UINT_MAX]. + This makes it easy on windows to reserve the positive integer range + for the index of a child and not clash with the unique ids. +*/ +QAccessible::Id QAccessibleCache::acquireId() const +{ + static const QAccessible::Id FirstId = QAccessible::Id(INT_MAX) + 1; + static QAccessible::Id lastUsedId = FirstId; + + while (idToInterface.contains(lastUsedId)) { + if (lastUsedId == UINT_MAX) // (wrap back when when we reach UINT_MAX) + lastUsedId = FirstId; + else + ++lastUsedId; + } + + return lastUsedId; +} + +QAccessibleInterface *QAccessibleCache::interfaceForId(QAccessible::Id id) const +{ + return idToInterface.value(id); +} + +QAccessible::Id QAccessibleCache::insert(QObject *object, QAccessibleInterface *iface) const +{ + Q_ASSERT(iface); + Q_UNUSED(object) + + // object might be 0 + Q_ASSERT(!objectToId.contains(object)); + Q_ASSERT_X(!idToInterface.values().contains(iface), "", "Accessible interface inserted into cache twice!"); + + QAccessible::Id id = acquireId(); + QObject *obj = iface->object(); + Q_ASSERT(object == obj); + if (obj) { + objectToId.insert(obj, id); + connect(obj, SIGNAL(destroyed(QObject *)), this, SLOT(objectDestroyed(QObject *))); + } + idToInterface.insert(id, iface); + return id; +} + +void QAccessibleCache::objectDestroyed(QObject* obj) +{ + QAccessible::Id id = objectToId.value(obj); + if (id) { + Q_ASSERT_X(idToInterface.contains(id), "", "QObject with accessible interface deleted, where interface not in cache!"); + deleteInterface(id, obj); + } +} + +void QAccessibleCache::deleteInterface(QAccessible::Id id, QObject *obj) +{ + QAccessibleInterface *iface = idToInterface.take(id); + if (!obj) + obj = iface->object(); + if (obj) + objectToId.remove(obj); + delete iface; +} + +QT_END_NAMESPACE diff --git a/src/gui/accessible/qaccessiblecache_p.h b/src/gui/accessible/qaccessiblecache_p.h new file mode 100644 index 0000000000..32f9c443ba --- /dev/null +++ b/src/gui/accessible/qaccessiblecache_p.h @@ -0,0 +1,78 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the QtGui module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QACCESSIBLECACHE_P +#define QACCESSIBLECACHE_P + +#include <QtCore/qglobal.h> +#include <QtCore/qobject.h> +#include <QtCore/qhash.h> + +#include "qaccessible.h" + +QT_BEGIN_NAMESPACE + + +class QAccessibleCache :public QObject +{ + Q_OBJECT + +public: + QAccessibleInterface *interfaceForId(QAccessible::Id id) const; + QAccessible::Id insert(QObject *object, QAccessibleInterface *iface) const; + void deleteInterface(QAccessible::Id id, QObject *obj = 0); + +private Q_SLOTS: + void objectDestroyed(QObject *obj); + +private: + QAccessible::Id acquireId() const; + + mutable QHash<QAccessible::Id, QAccessibleInterface *> idToInterface; + mutable QHash<QObject *, QAccessible::Id> objectToId; + + friend class QAccessible; + friend class QAccessibleInterface; +}; + +QT_END_NAMESPACE + +#endif diff --git a/src/gui/accessible/qaccessibleobject.cpp b/src/gui/accessible/qaccessibleobject.cpp index c1ef71e1fa..ccbfd36b70 100644 --- a/src/gui/accessible/qaccessibleobject.cpp +++ b/src/gui/accessible/qaccessibleobject.cpp @@ -132,11 +132,8 @@ QAccessibleInterface *QAccessibleObject::childAt(int x, int y) const for (int i = 0; i < childCount(); ++i) { QAccessibleInterface *childIface = child(i); Q_ASSERT(childIface); - if (childIface->rect().contains(x,y)) { + if (childIface->rect().contains(x,y)) return childIface; - } else { - delete childIface; - } } return 0; } @@ -176,7 +173,6 @@ static QObjectList topLevelObjects() if (QAccessibleInterface *root = w->accessibleRoot()) { if (root->object()) list.append(root->object()); - delete root; } } } diff --git a/src/platformsupport/linuxaccessibility/atspiadaptor.cpp b/src/platformsupport/linuxaccessibility/atspiadaptor.cpp index 050cb6a0bc..e4702e8497 100644 --- a/src/platformsupport/linuxaccessibility/atspiadaptor.cpp +++ b/src/platformsupport/linuxaccessibility/atspiadaptor.cpp @@ -587,7 +587,7 @@ QString AtSpiAdaptor::introspect(const QString &path) const " </interface>\n" ); - QAIPointer interface = interfaceFromPath(path); + QAccessibleInterface * interface = interfaceFromPath(path); if (!interface) { qAtspiDebug() << "WARNING Qt AtSpiAdaptor: Could not find accessible on path: " << path; return QString(); @@ -816,7 +816,6 @@ void AtSpiAdaptor::windowActivated(QObject* window, bool active) // in dtor it may be invalid if (iface->isValid()) windowTitle = iface->text(QAccessible::Name); - delete iface; QDBusVariant data; data.setVariant(windowTitle); @@ -854,48 +853,28 @@ bool AtSpiAdaptor::sendDBusSignal(const QString &path, const QString &interface, return m_dbus->connection().send(message); } -QAIPointer AtSpiAdaptor::interfaceFromPath(const QString& dbusPath) const +QAccessibleInterface *AtSpiAdaptor::interfaceFromPath(const QString& dbusPath) const { if (dbusPath == QLatin1String(QSPI_OBJECT_PATH_ROOT)) - return QAIPointer(QAccessible::queryAccessibleInterface(qApp)); + return QAccessible::queryAccessibleInterface(qApp); QStringList parts = dbusPath.split(QLatin1Char('/')); - if (parts.size() <= 5) { + if (parts.size() != 6) { qAtspiDebug() << "invalid path: " << dbusPath; - return QAIPointer(); + return 0; } QString objectString = parts.at(5); - quintptr uintptr = objectString.toULongLong(); - - if (uintptr && m_handledObjects.contains(uintptr)) { - // We found the pointer, check if it's still valid: - if (m_handledObjects[uintptr]) { - QObject* object = reinterpret_cast<QObject*>(uintptr); - - QAIPointer interface = QAIPointer(QAccessible::queryAccessibleInterface(object)); - if (!interface) - return QAIPointer(); - - for (int i = 6; i < parts.size(); ++i) { - int childIndex = parts.at(i).toInt(); - if (childIndex < 0) { - qAtspiDebug() << "Invalid child index"; - return QAIPointer(); - } - QAIPointer childInterface(interface->child(childIndex)); - if (childInterface) - interface = childInterface; - } - return interface; - } else { - m_handledObjects.remove(uintptr); - } - } - return QAIPointer(); + QAccessible::Id id = objectString.toUInt(); + + // The id is always in the range [INT_MAX+1, UINT_MAX] + if ((int)id >= 0) + qWarning() << "No accessible object found for id: " << id; + + return QAccessible::accessibleInterface(id); } -void AtSpiAdaptor::notifyStateChange(const QAIPointer &interface, const QString &state, int value) +void AtSpiAdaptor::notifyStateChange(QAccessibleInterface *interface, const QString &state, int value) { QString path = pathForInterface(interface); QVariantList stateArgs = packDBusSignalArguments(state, value, 0, variantForPath(path)); @@ -912,28 +891,28 @@ void AtSpiAdaptor::notify(QAccessibleEvent *event) switch (event->type()) { case QAccessible::ObjectCreated: if (sendObject || sendObject_children_changed) - notifyAboutCreation(QAIPointer(event->accessibleInterface())); + notifyAboutCreation(event->accessibleInterface()); break; case QAccessible::ObjectShow: { if (sendObject || sendObject_state_changed) { - notifyStateChange(QAIPointer(event->accessibleInterface()), QLatin1String("showing"), 1); + notifyStateChange(event->accessibleInterface(), QLatin1String("showing"), 1); } break; } case QAccessible::ObjectHide: { if (sendObject || sendObject_state_changed) { - notifyStateChange(QAIPointer(event->accessibleInterface()), QLatin1String("showing"), 0); + notifyStateChange(event->accessibleInterface(), QLatin1String("showing"), 0); } break; } case QAccessible::ObjectDestroyed: { if (sendObject || sendObject_state_changed) - notifyAboutDestruction(QAIPointer(event->accessibleInterface())); + notifyAboutDestruction(event->accessibleInterface()); break; } case QAccessible::NameChanged: { if (sendObject || sendObject_property_change || sendObject_property_change_accessible_name) { - QString path = pathForInterface(QAIPointer(event->accessibleInterface())); + QString path = pathForInterface(event->accessibleInterface()); QVariantList args = packDBusSignalArguments(QLatin1String("accessible-name"), 0, 0, variantForPath(path)); sendDBusSignal(path, QLatin1String(ATSPI_DBUS_INTERFACE_EVENT_OBJECT), QLatin1String("PropertyChange"), args); @@ -942,7 +921,7 @@ void AtSpiAdaptor::notify(QAccessibleEvent *event) } case QAccessible::DescriptionChanged: { if (sendObject || sendObject_property_change || sendObject_property_change_accessible_description) { - QString path = pathForInterface(QAIPointer(event->accessibleInterface())); + QString path = pathForInterface(event->accessibleInterface()); QVariantList args = packDBusSignalArguments(QLatin1String("accessible-description"), 0, 0, variantForPath(path)); sendDBusSignal(path, QLatin1String(ATSPI_DBUS_INTERFACE_EVENT_OBJECT), QLatin1String("PropertyChange"), args); @@ -951,14 +930,14 @@ void AtSpiAdaptor::notify(QAccessibleEvent *event) } case QAccessible::Focus: { if (sendFocus || sendObject || sendObject_state_changed) - sendFocusChanged(QAIPointer(event->accessibleInterface())); + sendFocusChanged(event->accessibleInterface()); break; } case QAccessible::TextInserted: case QAccessible::TextRemoved: case QAccessible::TextUpdated: { if (sendObject || sendObject_text_changed) { - QAIPointer iface = QAIPointer(event->accessibleInterface()); + QAccessibleInterface * iface = event->accessibleInterface(); if (!iface || !iface->textInterface()) { qAtspiDebug() << "Received text event for invalid interface."; return; @@ -1016,7 +995,7 @@ void AtSpiAdaptor::notify(QAccessibleEvent *event) } case QAccessible::TextCaretMoved: { if (sendObject || sendObject_text_caret_moved) { - QAIPointer iface = QAIPointer(event->accessibleInterface()); + QAccessibleInterface * iface = event->accessibleInterface(); if (!iface || !iface->textInterface()) { qWarning() << "Sending TextCaretMoved from object that does not implement text interface: " << iface; return; @@ -1034,7 +1013,7 @@ void AtSpiAdaptor::notify(QAccessibleEvent *event) } case QAccessible::TextSelectionChanged: { if (sendObject || sendObject_text_selection_changed) { - QAIPointer iface = QAIPointer(event->accessibleInterface()); + QAccessibleInterface * iface = event->accessibleInterface(); QString path = pathForInterface(iface); QVariantList args = packDBusSignalArguments(QString(), 0, 0, QVariant::fromValue(QDBusVariant(QVariant(QString())))); sendDBusSignal(path, QLatin1String(ATSPI_DBUS_INTERFACE_EVENT_OBJECT), @@ -1044,7 +1023,7 @@ void AtSpiAdaptor::notify(QAccessibleEvent *event) } case QAccessible::ValueChanged: { if (sendObject || sendObject_value_changed || sendObject_property_change_accessible_value) { - QAIPointer iface = QAIPointer(event->accessibleInterface()); + QAccessibleInterface * iface = event->accessibleInterface(); if (!iface || !iface->valueInterface()) { qWarning() << "ValueChanged event from invalid accessible: " << iface; return; @@ -1058,7 +1037,7 @@ void AtSpiAdaptor::notify(QAccessibleEvent *event) break; } case QAccessible::Selection: { - QAIPointer iface = QAIPointer(event->accessibleInterface()); + QAccessibleInterface * iface = event->accessibleInterface(); if (!iface) { qWarning() << "Selection event from invalid accessible."; return; @@ -1075,7 +1054,7 @@ void AtSpiAdaptor::notify(QAccessibleEvent *event) if (sendObject || sendObject_state_changed || sendWindow || sendWindow_activate) { QAccessible::State stateChange = static_cast<QAccessibleStateChangeEvent*>(event)->changedStates(); if (stateChange.checked) { - QAIPointer iface = QAIPointer(event->accessibleInterface()); + QAccessibleInterface * iface = event->accessibleInterface(); if (!iface) { qWarning() << "StateChanged event from invalid accessible."; return; @@ -1083,7 +1062,7 @@ void AtSpiAdaptor::notify(QAccessibleEvent *event) int checked = iface->state().checked; notifyStateChange(iface, QLatin1String("checked"), checked); } else if (stateChange.active) { - QAIPointer iface = QAIPointer(event->accessibleInterface()); + QAccessibleInterface * iface = event->accessibleInterface(); if (!iface || !(iface->role() == QAccessible::Window && (sendWindow || sendWindow_activate))) return; QString windowTitle = iface->text(QAccessible::Name); @@ -1098,7 +1077,7 @@ void AtSpiAdaptor::notify(QAccessibleEvent *event) int isActive = iface->state().active; notifyStateChange(iface, QLatin1String("active"), isActive); } else if (stateChange.disabled) { - QAIPointer iface = QAIPointer(event->accessibleInterface()); + QAccessibleInterface *iface = event->accessibleInterface(); QAccessible::State state = iface->state(); bool enabled = !state.disabled; @@ -1170,7 +1149,7 @@ void AtSpiAdaptor::notify(QAccessibleEvent *event) } } -void AtSpiAdaptor::sendFocusChanged(const QAIPointer &interface) const +void AtSpiAdaptor::sendFocusChanged(QAccessibleInterface *interface) const { static QString lastFocusPath; // "remove" old focus @@ -1194,13 +1173,13 @@ void AtSpiAdaptor::sendFocusChanged(const QAIPointer &interface) const } } -void AtSpiAdaptor::notifyAboutCreation(const QAIPointer &interface) const +void AtSpiAdaptor::notifyAboutCreation(QAccessibleInterface *interface) const { // // say hello to d-bus // cache->emitAddAccessible(accessible->getCacheItem()); // notify about the new child of our parent - QAIPointer parent(interface->parent()); + QAccessibleInterface * parent = interface->parent(); if (!parent) { qAtspiDebug() << "AtSpiAdaptor::notifyAboutCreation: Could not find parent for " << interface->object(); return; @@ -1212,12 +1191,12 @@ void AtSpiAdaptor::notifyAboutCreation(const QAIPointer &interface) const sendDBusSignal(parentPath, QLatin1String(ATSPI_DBUS_INTERFACE_EVENT_OBJECT), QLatin1String("ChildrenChanged"), args); } -void AtSpiAdaptor::notifyAboutDestruction(const QAIPointer &interface) const +void AtSpiAdaptor::notifyAboutDestruction(QAccessibleInterface *interface) const { if (!interface || !interface->isValid()) return; - QAIPointer parent(interface->parent()); + QAccessibleInterface * parent = interface->parent(); if (!parent) { qAtspiDebug() << "AtSpiAdaptor::notifyAboutDestruction: Could not find parent for " << interface->object(); return; @@ -1233,7 +1212,7 @@ void AtSpiAdaptor::notifyAboutDestruction(const QAIPointer &interface) const // childIndex = parent->indexOfChild(interface); // } - QString parentPath = pathForInterface(parent, true); + QString parentPath = pathForInterface(parent); QVariantList args = packDBusSignalArguments(QLatin1String("remove"), childIndex, 0, variantForPath(path)); sendDBusSignal(parentPath, QLatin1String(ATSPI_DBUS_INTERFACE_EVENT_OBJECT), QLatin1String("ChildrenChanged"), args); } @@ -1245,7 +1224,7 @@ void AtSpiAdaptor::notifyAboutDestruction(const QAIPointer &interface) const bool AtSpiAdaptor::handleMessage(const QDBusMessage &message, const QDBusConnection &connection) { // get accessible interface - QAIPointer accessible = interfaceFromPath(message.path()); + QAccessibleInterface * accessible = interfaceFromPath(message.path()); if (!accessible) { qAtspiDebug() << "WARNING Qt AtSpiAdaptor: Could not find accessible on path: " << message.path(); return false; @@ -1295,7 +1274,7 @@ bool AtSpiAdaptor::handleMessage(const QDBusMessage &message, const QDBusConnect } // Application -bool AtSpiAdaptor::applicationInterface(const QAIPointer &interface, const QString &function, const QDBusMessage &message, const QDBusConnection &connection) +bool AtSpiAdaptor::applicationInterface(QAccessibleInterface *interface, const QString &function, const QDBusMessage &message, const QDBusConnection &connection) { if (message.path() != QLatin1String(ATSPI_DBUS_PATH_ROOT)) { qAtspiDebug() << "WARNING Qt AtSpiAdaptor: Could not find application interface for: " << message.path() << interface; @@ -1358,7 +1337,7 @@ void AtSpiAdaptor::registerApplication() } // Accessible -bool AtSpiAdaptor::accessibleInterface(const QAIPointer &interface, const QString &function, const QDBusMessage &message, const QDBusConnection &connection) +bool AtSpiAdaptor::accessibleInterface(QAccessibleInterface *interface, const QString &function, const QDBusMessage &message, const QDBusConnection &connection) { if (function == QLatin1String("GetRole")) { sendReply(connection, message, (uint) getRole(interface)); @@ -1372,9 +1351,9 @@ bool AtSpiAdaptor::accessibleInterface(const QAIPointer &interface, const QStrin sendReply(connection, message, QVariant::fromValue(QDBusVariant(interface->childCount()))); } else if (function == QLatin1String("GetIndexInParent")) { int childIndex = -1; - QAIPointer parent(interface->parent()); + QAccessibleInterface * parent = interface->parent(); if (parent) { - childIndex = parent->indexOfChild(interface.data()); + childIndex = parent->indexOfChild(interface); if (childIndex < 0) { qAtspiDebug() << "GetIndexInParent get invalid index: " << childIndex << interface; } @@ -1382,7 +1361,7 @@ bool AtSpiAdaptor::accessibleInterface(const QAIPointer &interface, const QStrin sendReply(connection, message, childIndex); } else if (function == QLatin1String("GetParent")) { QString path; - QAIPointer parent(interface->parent()); + QAccessibleInterface * parent = interface->parent(); if (!parent) { path = QLatin1String(ATSPI_DBUS_PATH_NULL); } else if (parent->role() == QAccessible::Application) { @@ -1399,7 +1378,7 @@ bool AtSpiAdaptor::accessibleInterface(const QAIPointer &interface, const QStrin sendReply(connection, message, QVariant::fromValue( QSpiObjectReference(connection, QDBusObjectPath(ATSPI_DBUS_PATH_NULL)))); } else { - QAIPointer childInterface = QAIPointer(interface->child(index)); + QAccessibleInterface * childInterface = interface->child(index); sendReply(connection, message, QVariant::fromValue( QSpiObjectReference(connection, QDBusObjectPath(pathForInterface(childInterface))))); } @@ -1440,7 +1419,7 @@ bool AtSpiAdaptor::accessibleInterface(const QAIPointer &interface, const QStrin } else if (function == QLatin1String("GetChildren")) { QSpiObjectReferenceArray children; for (int i = 0; i < interface->childCount(); ++i) { - QString childPath = pathForInterface(QAIPointer(interface->child(i))); + QString childPath = pathForInterface(interface->child(i)); QSpiObjectReference ref(connection, QDBusObjectPath(childPath)); children << ref; } @@ -1452,7 +1431,7 @@ bool AtSpiAdaptor::accessibleInterface(const QAIPointer &interface, const QStrin return true; } -AtspiRole AtSpiAdaptor::getRole(const QAIPointer &interface) const +AtspiRole AtSpiAdaptor::getRole(QAccessibleInterface *interface) const { if ((interface->role() == QAccessible::EditableText) && interface->state().passwordEdit) return ATSPI_ROLE_PASSWORD_TEXT; @@ -1461,7 +1440,7 @@ AtspiRole AtSpiAdaptor::getRole(const QAIPointer &interface) const //#define ACCESSIBLE_CREATION_DEBUG -QStringList AtSpiAdaptor::accessibleInterfaces(const QAIPointer &interface) const +QStringList AtSpiAdaptor::accessibleInterfaces(QAccessibleInterface *interface) const { QStringList ifaces; #ifdef ACCESSIBLE_CREATION_DEBUG @@ -1505,7 +1484,7 @@ QStringList AtSpiAdaptor::accessibleInterfaces(const QAIPointer &interface) cons return ifaces; } -QSpiRelationArray AtSpiAdaptor::relationSet(const QAIPointer &interface, const QDBusConnection &connection) const +QSpiRelationArray AtSpiAdaptor::relationSet(QAccessibleInterface *interface, const QDBusConnection &connection) const { typedef QPair<QAccessibleInterface*, QAccessible::Relation> RelationPair; QVector<RelationPair> relationInterfaces; @@ -1517,7 +1496,7 @@ QSpiRelationArray AtSpiAdaptor::relationSet(const QAIPointer &interface, const Q //And why is it a list, when it always have one item? And it seems to assume that the QAccessible::Relation enum maps directly to AtSpi QList<QSpiObjectReference> related; - QDBusObjectPath path = QDBusObjectPath(pathForInterface(QAIPointer(pair.first))); + QDBusObjectPath path = QDBusObjectPath(pathForInterface(pair.first)); related.append(QSpiObjectReference(connection, path)); if (!related.isEmpty()) @@ -1537,56 +1516,24 @@ QString AtSpiAdaptor::pathForObject(QObject *object) const { Q_ASSERT(object); - if (object == qApp) { - return QLatin1String(QSPI_OBJECT_PATH_ROOT); - } - - if (qstrcmp(object->metaObject()->className(), "QAction") == 0) { + if (inheritsQAction(object)) { qAtspiDebug() << "AtSpiAdaptor::pathForObject: warning: creating path with QAction as object."; } - quintptr uintptr = reinterpret_cast<quintptr>(object); - if (!m_handledObjects.contains(uintptr) || m_handledObjects.value(uintptr) == 0) - m_handledObjects[uintptr] = QPointer<QObject>(object); - return QLatin1String(QSPI_OBJECT_PATH_PREFIX) + QString::number(uintptr); + + QAccessibleInterface *iface = QAccessible::queryAccessibleInterface(object); + return pathForInterface(iface); } -QString AtSpiAdaptor::pathForInterface(const QAIPointer &interface, bool inDestructor) const +QString AtSpiAdaptor::pathForInterface(QAccessibleInterface *interface) const { if (!interface || !interface->isValid()) return QLatin1String(ATSPI_DBUS_PATH_NULL); if (interface->role() == QAccessible::Application) return QLatin1String(QSPI_OBJECT_PATH_ROOT); - QAIPointer interfaceWithObject = interface; - QString path; - - QAccessible::Role role = interface->role(); - if (((role == QAccessible::MenuItem) || (role == QAccessible::Separator)) && - interface->object() && inheritsQAction(interface->object())) { - interfaceWithObject = QAIPointer(interface->parent()); - int childIndex = interfaceWithObject->indexOfChild(interface.data()); - path.append(QString::fromLatin1("/%1").arg(childIndex)); - } - - while (!interfaceWithObject->object()) { - QAIPointer parentInterface(interfaceWithObject->parent()); - - Q_ASSERT(parentInterface->isValid()); - int index = parentInterface->indexOfChild(interfaceWithObject.data()); - if (index < 0) { - qAtspiDebug() << "Object claims to have child that we cannot navigate to. FIX IT!" << parentInterface->object(); - return QLatin1String(ATSPI_DBUS_PATH_NULL); - } - path.prepend(QLatin1Char('/') + QString::number(index)); - interfaceWithObject = parentInterface; - } - quintptr uintptr = reinterpret_cast<quintptr>(interfaceWithObject->object()); - path.prepend(QLatin1String(QSPI_OBJECT_PATH_PREFIX) + QString::number(uintptr)); - - if (!inDestructor && (!m_handledObjects.contains(uintptr) || m_handledObjects.value(uintptr) == 0)) - m_handledObjects[uintptr] = QPointer<QObject>(interfaceWithObject->object()); - - return path; + QAccessible::Id id = QAccessible::uniqueId(interface); + Q_ASSERT((int)id < 0); + return QLatin1String(QSPI_OBJECT_PATH_PREFIX) + QString::number(id); } bool AtSpiAdaptor::inheritsQAction(QObject *object) @@ -1602,21 +1549,21 @@ bool AtSpiAdaptor::inheritsQAction(QObject *object) } // Component -static QAIPointer getWindow(QAIPointer interface) +static QAccessibleInterface * getWindow(QAccessibleInterface * interface) { if (interface->role() == QAccessible::Window) return interface; - QAIPointer parent(interface->parent()); + QAccessibleInterface * parent = interface->parent(); while (parent && parent->role() != QAccessible::Window) - parent = QAIPointer(parent->parent()); + parent = parent->parent(); return parent; } -static QRect getRelativeRect(const QAIPointer &interface) +static QRect getRelativeRect(QAccessibleInterface *interface) { - QAIPointer window; + QAccessibleInterface * window; QRect wr, cr; cr = interface->rect(); @@ -1631,7 +1578,7 @@ static QRect getRelativeRect(const QAIPointer &interface) return cr; } -bool AtSpiAdaptor::componentInterface(const QAIPointer &interface, const QString &function, const QDBusMessage &message, const QDBusConnection &connection) +bool AtSpiAdaptor::componentInterface(QAccessibleInterface *interface, const QString &function, const QDBusMessage &message, const QDBusConnection &connection) { if (function == QLatin1String("Contains")) { bool ret = false; @@ -1649,11 +1596,11 @@ bool AtSpiAdaptor::componentInterface(const QAIPointer &interface, const QString uint coordType = message.arguments().at(2).toUInt(); Q_UNUSED (coordType) // FIXME - QAIPointer childInterface(interface->childAt(x, y)); - QAIPointer iface; + QAccessibleInterface * childInterface(interface->childAt(x, y)); + QAccessibleInterface * iface = 0; while (childInterface) { iface = childInterface; - childInterface = QAIPointer(iface->childAt(x, y)); + childInterface = iface->childAt(x, y); } if (iface) { QString path = pathForInterface(iface); @@ -1721,13 +1668,13 @@ bool AtSpiAdaptor::componentInterface(const QAIPointer &interface, const QString return true; } -QRect AtSpiAdaptor::getExtents(const QAIPointer &interface, uint coordType) +QRect AtSpiAdaptor::getExtents(QAccessibleInterface *interface, uint coordType) { return (coordType == ATSPI_COORD_TYPE_SCREEN) ? interface->rect() : getRelativeRect(interface); } // Action interface -bool AtSpiAdaptor::actionInterface(const QAIPointer &interface, const QString &function, const QDBusMessage &message, const QDBusConnection &connection) +bool AtSpiAdaptor::actionInterface(QAccessibleInterface *interface, const QString &function, const QDBusMessage &message, const QDBusConnection &connection) { QAccessibleActionInterface *actionIface = interface->actionInterface(); if (!actionIface) @@ -1797,7 +1744,7 @@ QSpiActionArray AtSpiAdaptor::getActions(QAccessibleActionInterface *actionInter } // Text interface -bool AtSpiAdaptor::textInterface(const QAIPointer &interface, const QString &function, const QDBusMessage &message, const QDBusConnection &connection) +bool AtSpiAdaptor::textInterface(QAccessibleInterface *interface, const QString &function, const QDBusMessage &message, const QDBusConnection &connection) { if (!interface->textInterface()) return false; @@ -1952,7 +1899,7 @@ QAccessible2::BoundaryType AtSpiAdaptor::qAccessibleBoundaryType(int atspiTextBo } // FIXME all attribute methods below should share code -QVariantList AtSpiAdaptor::getAttributes(const QAIPointer &interface, int offset, bool includeDefaults) const +QVariantList AtSpiAdaptor::getAttributes(QAccessibleInterface *interface, int offset, bool includeDefaults) const { Q_UNUSED(includeDefaults); @@ -1974,7 +1921,7 @@ QVariantList AtSpiAdaptor::getAttributes(const QAIPointer &interface, int offset return list; } -QVariantList AtSpiAdaptor::getAttributeValue(const QAIPointer &interface, int offset, const QString &attributeName) const +QVariantList AtSpiAdaptor::getAttributeValue(QAccessibleInterface *interface, int offset, const QString &attributeName) const { QString mapped; QString joined; @@ -1998,7 +1945,7 @@ QVariantList AtSpiAdaptor::getAttributeValue(const QAIPointer &interface, int of return list; } -QRect AtSpiAdaptor::getCharacterExtents(const QAIPointer &interface, int offset, uint coordType) const +QRect AtSpiAdaptor::getCharacterExtents(QAccessibleInterface *interface, int offset, uint coordType) const { QRect rect = interface->textInterface()->characterRect(offset); @@ -2008,7 +1955,7 @@ QRect AtSpiAdaptor::getCharacterExtents(const QAIPointer &interface, int offset, return rect; } -QRect AtSpiAdaptor::getRangeExtents(const QAIPointer &interface, +QRect AtSpiAdaptor::getRangeExtents(QAccessibleInterface *interface, int startOffset, int endOffset, uint coordType) const { if (endOffset == -1) @@ -2029,9 +1976,9 @@ QRect AtSpiAdaptor::getRangeExtents(const QAIPointer &interface, return rect; } -QRect AtSpiAdaptor::translateRectToWindowCoordinates(const QAIPointer &interface, const QRect &rect) +QRect AtSpiAdaptor::translateRectToWindowCoordinates(QAccessibleInterface *interface, const QRect &rect) { - QAIPointer window = getWindow(interface); + QAccessibleInterface * window = getWindow(interface); if (window) return rect.translated(-window->rect().x(), -window->rect().y()); @@ -2065,13 +2012,13 @@ static void replaceTextFallback(QAccessibleInterface *accessible, long startOffs accessible->setText(QAccessible::Value, t); } -bool AtSpiAdaptor::editableTextInterface(const QAIPointer &interface, const QString &function, const QDBusMessage &message, const QDBusConnection &connection) +bool AtSpiAdaptor::editableTextInterface(QAccessibleInterface *interface, const QString &function, const QDBusMessage &message, const QDBusConnection &connection) { if (function == QLatin1String("CopyText")) { #ifndef QT_NO_CLIPBOARD int startOffset = message.arguments().at(0).toInt(); int endOffset = message.arguments().at(1).toInt(); - const QString t = textForRange(interface.data(), startOffset, endOffset); + const QString t = textForRange(interface, startOffset, endOffset); QGuiApplication::clipboard()->setText(t); #endif connection.send(message.createReply(true)); @@ -2079,11 +2026,11 @@ bool AtSpiAdaptor::editableTextInterface(const QAIPointer &interface, const QStr #ifndef QT_NO_CLIPBOARD int startOffset = message.arguments().at(0).toInt(); int endOffset = message.arguments().at(1).toInt(); - const QString t = textForRange(interface.data(), startOffset, endOffset); + const QString t = textForRange(interface, startOffset, endOffset); if (QAccessibleEditableTextInterface *editableTextIface = interface->editableTextInterface()) editableTextIface->deleteText(startOffset, endOffset); else - replaceTextFallback(interface.data(), startOffset, endOffset, QString()); + replaceTextFallback(interface, startOffset, endOffset, QString()); QGuiApplication::clipboard()->setText(t); #endif connection.send(message.createReply(true)); @@ -2093,7 +2040,7 @@ bool AtSpiAdaptor::editableTextInterface(const QAIPointer &interface, const QStr if (QAccessibleEditableTextInterface *editableTextIface = interface->editableTextInterface()) editableTextIface->deleteText(startOffset, endOffset); else - replaceTextFallback(interface.data(), startOffset, endOffset, QString()); + replaceTextFallback(interface, startOffset, endOffset, QString()); connection.send(message.createReply(true)); } else if (function == QLatin1String("InsertText")) { int position = message.arguments().at(0).toInt(); @@ -2103,7 +2050,7 @@ bool AtSpiAdaptor::editableTextInterface(const QAIPointer &interface, const QStr if (QAccessibleEditableTextInterface *editableTextIface = interface->editableTextInterface()) editableTextIface->insertText(position, text); else - replaceTextFallback(interface.data(), position, position, text); + replaceTextFallback(interface, position, position, text); connection.send(message.createReply(true)); } else if (function == QLatin1String("PasteText")) { #ifndef QT_NO_CLIPBOARD @@ -2112,7 +2059,7 @@ bool AtSpiAdaptor::editableTextInterface(const QAIPointer &interface, const QStr if (QAccessibleEditableTextInterface *editableTextIface = interface->editableTextInterface()) editableTextIface->insertText(position, txt); else - replaceTextFallback(interface.data(), position, position, txt); + replaceTextFallback(interface, position, position, txt); #endif connection.send(message.createReply(true)); } else if (function == QLatin1String("SetTextContents")) { @@ -2129,7 +2076,7 @@ bool AtSpiAdaptor::editableTextInterface(const QAIPointer &interface, const QStr } // Value interface -bool AtSpiAdaptor::valueInterface(const QAIPointer &interface, const QString &function, const QDBusMessage &message, const QDBusConnection &connection) +bool AtSpiAdaptor::valueInterface(QAccessibleInterface *interface, const QString &function, const QDBusMessage &message, const QDBusConnection &connection) { if (function == QLatin1String("SetCurrentValue")) { QDBusVariant v = message.arguments().at(2).value<QDBusVariant>(); @@ -2165,7 +2112,7 @@ bool AtSpiAdaptor::valueInterface(const QAIPointer &interface, const QString &fu } // Table interface -bool AtSpiAdaptor::tableInterface(const QAIPointer &interface, const QString &function, const QDBusMessage &message, const QDBusConnection &connection) +bool AtSpiAdaptor::tableInterface(QAccessibleInterface *interface, const QString &function, const QDBusMessage &message, const QDBusConnection &connection) { if (!(interface->tableInterface() || interface->tableCellInterface())) { qAtspiDebug() << "WARNING Qt AtSpiAdaptor: Could not find table interface for: " << message.path() << interface; @@ -2175,7 +2122,7 @@ bool AtSpiAdaptor::tableInterface(const QAIPointer &interface, const QString &fu if (0) { // properties } else if (function == QLatin1String("GetCaption")) { - QAIPointer captionInterface= QAIPointer(interface->tableInterface()->caption()); + QAccessibleInterface * captionInterface= interface->tableInterface()->caption(); if (captionInterface) { QSpiObjectReference ref = QSpiObjectReference(connection, QDBusObjectPath(pathForInterface(captionInterface))); sendReply(connection, message, QVariant::fromValue(ref)); @@ -2196,7 +2143,7 @@ bool AtSpiAdaptor::tableInterface(const QAIPointer &interface, const QString &fu connection.send(message.createReply(QVariant::fromValue(QDBusVariant( QVariant::fromValue(interface->tableInterface()->selectedRowCount()))))); } else if (function == QLatin1String("GetSummary")) { - QAIPointer summary = interface->tableInterface() ? QAIPointer(interface->tableInterface()->summary()) : QAIPointer(0); + QAccessibleInterface * summary = interface->tableInterface() ? interface->tableInterface()->summary() : 0; QSpiObjectReference ref(connection, QDBusObjectPath(pathForInterface(summary))); connection.send(message.createReply(QVariant::fromValue(QDBusVariant(QVariant::fromValue(ref))))); } else if (function == QLatin1String("GetAccessibleAt")) { @@ -2211,7 +2158,7 @@ bool AtSpiAdaptor::tableInterface(const QAIPointer &interface, const QString &fu } QSpiObjectReference ref; - QAIPointer cell(interface->tableInterface()->cellAt(row, column)); + QAccessibleInterface * cell(interface->tableInterface()->cellAt(row, column)); if (cell) { ref = QSpiObjectReference(connection, QDBusObjectPath(pathForInterface(cell))); } else { @@ -2231,13 +2178,12 @@ bool AtSpiAdaptor::tableInterface(const QAIPointer &interface, const QString &fu int index = interface->indexOfChild(cell); qAtspiDebug() << "QSpiAdaptor::GetIndexAt row:" << row << " col:" << column << " logical index:" << index; Q_ASSERT(index > 0); - delete cell; connection.send(message.createReply(index)); } else if ((function == QLatin1String("GetColumnAtIndex")) || (function == QLatin1String("GetRowAtIndex"))) { int index = message.arguments().at(0).toInt(); int ret = -1; if (index >= 0) { - QAIPointer cell = QAIPointer(interface->child(index)); + QAccessibleInterface * cell = interface->child(index); if (cell) { if (function == QLatin1String("GetColumnAtIndex")) { if (cell->role() == QAccessible::ColumnHeader) { @@ -2294,7 +2240,6 @@ bool AtSpiAdaptor::tableInterface(const QAIPointer &interface, const QString &fu if (cell) { cell->rowColumnExtents(&row, &col, &rowExtents, &colExtents, &isSelected); success = true; - delete cell; } QVariantList list; @@ -2315,12 +2260,11 @@ bool AtSpiAdaptor::tableInterface(const QAIPointer &interface, const QString &fu int column = message.arguments().at(0).toInt(); QSpiObjectReference ref; - QAIPointer cell(interface->tableInterface()->cellAt(0, column)); + QAccessibleInterface * cell(interface->tableInterface()->cellAt(0, column)); if (cell && cell->tableCellInterface()) { QList<QAccessibleInterface*> header = cell->tableCellInterface()->columnHeaderCells(); if (header.size() > 0) { - ref = QSpiObjectReference(connection, QDBusObjectPath(pathForInterface(QAIPointer(header.takeAt(0))))); - qDeleteAll(header); + ref = QSpiObjectReference(connection, QDBusObjectPath(pathForInterface(header.takeAt(0)))); } } connection.send(message.createReply(QVariant::fromValue(ref))); @@ -2331,10 +2275,8 @@ bool AtSpiAdaptor::tableInterface(const QAIPointer &interface, const QString &fu QAccessibleTableCellInterface *cell = interface->tableInterface()->cellAt(row, 0)->tableCellInterface(); if (cell) { QList<QAccessibleInterface*> header = cell->rowHeaderCells(); - delete cell; if (header.size() > 0) { - ref = QSpiObjectReference(connection, QDBusObjectPath(pathForInterface(QAIPointer(header.takeAt(0))))); - qDeleteAll(header); + ref = QSpiObjectReference(connection, QDBusObjectPath(pathForInterface(header.takeAt(0)))); } } connection.send(message.createReply(QVariant::fromValue(ref))); @@ -2354,7 +2296,6 @@ bool AtSpiAdaptor::tableInterface(const QAIPointer &interface, const QString &fu int column = message.arguments().at(1).toInt(); QAccessibleTableCellInterface* cell = interface->tableInterface()->cellAt(row, column)->tableCellInterface(); connection.send(message.createReply(cell->isSelected())); - delete cell; } else if (function == QLatin1String("AddColumnSelection")) { int column = message.arguments().at(0).toInt(); connection.send(message.createReply(interface->tableInterface()->selectColumn(column))); diff --git a/src/platformsupport/linuxaccessibility/atspiadaptor_p.h b/src/platformsupport/linuxaccessibility/atspiadaptor_p.h index 0bc3290baa..aafaecfeae 100644 --- a/src/platformsupport/linuxaccessibility/atspiadaptor_p.h +++ b/src/platformsupport/linuxaccessibility/atspiadaptor_p.h @@ -59,7 +59,6 @@ class QAccessibleInterface; class QSpiAccessibleInterface; class QSpiApplicationAdaptor; -typedef QSharedPointer<QAccessibleInterface> QAIPointer; class AtSpiAdaptor :public QDBusVirtualObject { @@ -90,45 +89,45 @@ private: bool sendDBusSignal(const QString &path, const QString &interface, const QString &name, const QVariantList &arguments) const; QVariant variantForPath(const QString &path) const; - void sendFocusChanged(const QAIPointer &interface) const; - void notifyAboutCreation(const QAIPointer &interface) const; - void notifyAboutDestruction(const QAIPointer &interface) const; + void sendFocusChanged(QAccessibleInterface *interface) const; + void notifyAboutCreation(QAccessibleInterface *interface) const; + void notifyAboutDestruction(QAccessibleInterface *interface) const; // handlers for the different accessible interfaces - bool applicationInterface(const QAIPointer &interface, const QString &function, const QDBusMessage &message, const QDBusConnection &connection); - bool accessibleInterface(const QAIPointer &interface, const QString &function, const QDBusMessage &message, const QDBusConnection &connection); - bool componentInterface(const QAIPointer &interface, const QString &function, const QDBusMessage &message, const QDBusConnection &connection); - bool actionInterface(const QAIPointer &interface, const QString &function, const QDBusMessage &message, const QDBusConnection &connection); - bool textInterface(const QAIPointer &interface, const QString &function, const QDBusMessage &message, const QDBusConnection &connection); - bool editableTextInterface(const QAIPointer &interface, const QString &function, const QDBusMessage &message, const QDBusConnection &connection); - bool valueInterface(const QAIPointer &interface, const QString &function, const QDBusMessage &message, const QDBusConnection &connection); - bool tableInterface(const QAIPointer &interface, const QString &function, const QDBusMessage &message, const QDBusConnection &connection); + bool applicationInterface(QAccessibleInterface *interface, const QString &function, const QDBusMessage &message, const QDBusConnection &connection); + bool accessibleInterface(QAccessibleInterface *interface, const QString &function, const QDBusMessage &message, const QDBusConnection &connection); + bool componentInterface(QAccessibleInterface *interface, const QString &function, const QDBusMessage &message, const QDBusConnection &connection); + bool actionInterface(QAccessibleInterface *interface, const QString &function, const QDBusMessage &message, const QDBusConnection &connection); + bool textInterface(QAccessibleInterface *interface, const QString &function, const QDBusMessage &message, const QDBusConnection &connection); + bool editableTextInterface(QAccessibleInterface *interface, const QString &function, const QDBusMessage &message, const QDBusConnection &connection); + bool valueInterface(QAccessibleInterface *interface, const QString &function, const QDBusMessage &message, const QDBusConnection &connection); + bool tableInterface(QAccessibleInterface *interface, const QString &function, const QDBusMessage &message, const QDBusConnection &connection); void sendReply(const QDBusConnection &connection, const QDBusMessage &message, const QVariant &argument) const; - QAIPointer interfaceFromPath(const QString& dbusPath) const; - QString pathForInterface(const QAIPointer &interface, bool inDestructor = false) const; + QAccessibleInterface *interfaceFromPath(const QString& dbusPath) const; + QString pathForInterface(QAccessibleInterface *interface) const; QString pathForObject(QObject *object) const; - void notifyStateChange(const QAIPointer& interface, const QString& state, int value); + void notifyStateChange(QAccessibleInterface *interface, const QString& state, int value); // accessible helper functions - AtspiRole getRole(const QAIPointer &interface) const; - QSpiRelationArray relationSet(const QAIPointer &interface, const QDBusConnection &connection) const; - QStringList accessibleInterfaces(const QAIPointer &interface) const; + AtspiRole getRole(QAccessibleInterface *interface) const; + QSpiRelationArray relationSet(QAccessibleInterface *interface, const QDBusConnection &connection) const; + QStringList accessibleInterfaces(QAccessibleInterface *interface) const; // component helper functions - static QRect getExtents(const QAIPointer &interface, uint coordType); - static QRect translateRectToWindowCoordinates(const QAIPointer &interface, const QRect &rect); + static QRect getExtents(QAccessibleInterface *interface, uint coordType); + static QRect translateRectToWindowCoordinates(QAccessibleInterface *interface, const QRect &rect); // action helper functions QSpiActionArray getActions(QAccessibleActionInterface* interface) const; // text helper functions - QVariantList getAttributes(const QAIPointer &, int offset, bool includeDefaults) const; - QVariantList getAttributeValue(const QAIPointer &, int offset, const QString &attributeName) const; - QRect getCharacterExtents(const QAIPointer &, int offset, uint coordType) const; - QRect getRangeExtents(const QAIPointer &, int startOffset, int endOffset, uint coordType) const; + QVariantList getAttributes(QAccessibleInterface *, int offset, bool includeDefaults) const; + QVariantList getAttributeValue(QAccessibleInterface *, int offset, const QString &attributeName) const; + QRect getCharacterExtents(QAccessibleInterface *, int offset, uint coordType) const; + QRect getRangeExtents(QAccessibleInterface *, int startOffset, int endOffset, uint coordType) const; QAccessible2::BoundaryType qAccessibleBoundaryType(int atspiTextBoundaryType) const; static bool inheritsQAction(QObject *object); @@ -140,8 +139,6 @@ private: /// Assigned from the accessibility registry. int m_applicationId; - mutable QHash<quintptr, QPointer<QObject> > m_handledObjects; - // Bit fields - which updates to send // AT-SPI has some events that we do not care about: diff --git a/src/plugins/accessible/widgets/complexwidgets.cpp b/src/plugins/accessible/widgets/complexwidgets.cpp index b805e8c967..9dbf7d7e0f 100644 --- a/src/plugins/accessible/widgets/complexwidgets.cpp +++ b/src/plugins/accessible/widgets/complexwidgets.cpp @@ -96,7 +96,6 @@ public: QAccessible::State state() const { QAccessibleInterface *parentInterface = parent(); QAccessible::State state = parentInterface->state(); - delete parentInterface; return state; } QRect rect() const { @@ -153,6 +152,12 @@ QAccessibleTabBar::QAccessibleTabBar(QWidget *w) Q_ASSERT(tabBar()); } +QAccessibleTabBar::~QAccessibleTabBar() +{ + foreach (QAccessible::Id id, m_childInterfaces.values()) + QAccessible::deleteAccessibleInterface(id); +} + /*! Returns the QTabBar. */ QTabBar *QAccessibleTabBar::tabBar() const { @@ -161,9 +166,14 @@ QTabBar *QAccessibleTabBar::tabBar() const QAccessibleInterface* QAccessibleTabBar::child(int index) const { + if (QAccessible::Id id = m_childInterfaces.value(index)) + return QAccessible::accessibleInterface(id); + // first the tabs, then 2 buttons if (index < tabBar()->count()) { QAccessibleTabButton *button = new QAccessibleTabButton(tabBar(), index); + QAccessible::registerAccessibleInterface(button); + m_childInterfaces.insert(index, QAccessible::uniqueId(button)); return button; } else if (index >= tabBar()->count()) { // left button diff --git a/src/plugins/accessible/widgets/complexwidgets.h b/src/plugins/accessible/widgets/complexwidgets.h index 32f67c9c69..306eae4a72 100644 --- a/src/plugins/accessible/widgets/complexwidgets.h +++ b/src/plugins/accessible/widgets/complexwidgets.h @@ -47,6 +47,7 @@ #include <QtWidgets/qabstractitemview.h> #include <QtGui/private/qaccessible2_p.h> + QT_BEGIN_NAMESPACE #ifndef QT_NO_ACCESSIBILITY @@ -101,6 +102,7 @@ class QAccessibleTabBar : public QAccessibleWidget { public: explicit QAccessibleTabBar(QWidget *w); + ~QAccessibleTabBar(); int childCount() const; QString text(QAccessible::Text t) const; @@ -113,6 +115,7 @@ public: protected: QTabBar *tabBar() const; + mutable QHash<int, QAccessible::Id> m_childInterfaces; }; #endif // QT_NO_TABBAR diff --git a/src/plugins/accessible/widgets/itemviews.cpp b/src/plugins/accessible/widgets/itemviews.cpp index 822d9d8c77..4ddd39f7ea 100644 --- a/src/plugins/accessible/widgets/itemviews.cpp +++ b/src/plugins/accessible/widgets/itemviews.cpp @@ -47,7 +47,6 @@ #include <qtreeview.h> #include <private/qtreewidget_p.h> #include <QtGui/private/qaccessible2_p.h> -#include <QtWidgets/private/qwidget_p.h> #ifndef QT_NO_ACCESSIBILITY @@ -82,43 +81,6 @@ int QAccessibleTable::logicalIndex(const QModelIndex &index) const return (index.row() + hHeader)*(index.model()->columnCount() + vHeader) + (index.column() + vHeader); } -QAccessibleInterface *QAccessibleTable::childFromLogical(int logicalIndex) const -{ - if (!view()->model()) - return 0; - - int vHeader = verticalHeader() ? 1 : 0; - int hHeader = horizontalHeader() ? 1 : 0; - - int columns = view()->model()->columnCount() + vHeader; - - int row = logicalIndex / columns; - int column = logicalIndex % columns; - - if (vHeader) { - if (column == 0) { - if (row == 0) { - return new QAccessibleTableCornerButton(view()); - } - return new QAccessibleTableHeaderCell(view(), row-1, Qt::Vertical); - } - --column; - } - if (hHeader) { - if (row == 0) { - return new QAccessibleTableHeaderCell(view(), column, Qt::Horizontal); - } - --row; - } - - QModelIndex index = view()->model()->index(row, column, view()->rootIndex()); - if (!index.isValid()) { - qWarning() << "QAccessibleTable::childFromLogical: Invalid index at: " << row << column; - return 0; - } - return new QAccessibleTableCell(view(), index, cellRole()); -} - QAccessibleTable::QAccessibleTable(QWidget *w) : QAccessibleObject(w) { @@ -143,6 +105,8 @@ bool QAccessibleTable::isValid() const QAccessibleTable::~QAccessibleTable() { + Q_FOREACH (QAccessible::Id id, childToId.values()) + QAccessible::deleteAccessibleInterface(id); } QHeaderView *QAccessibleTable::horizontalHeader() const @@ -173,13 +137,6 @@ QHeaderView *QAccessibleTable::verticalHeader() const return header; } -QAccessibleTableCell *QAccessibleTable::cell(const QModelIndex &index) const -{ - if (index.isValid()) - return new QAccessibleTableCell(view(), index, cellRole()); - return 0; -} - QAccessibleInterface *QAccessibleTable::cellAt(int row, int column) const { if (!view()->model()) @@ -190,7 +147,7 @@ QAccessibleInterface *QAccessibleTable::cellAt(int row, int column) const qWarning() << "QAccessibleTable::cellAt: invalid index: " << index << " for " << view(); return 0; } - return cell(index); + return child(logicalIndex(index)); } QAccessibleInterface *QAccessibleTable::caption() const @@ -252,9 +209,8 @@ QList<QAccessibleInterface *> QAccessibleTable::selectedCells() const QList<QAccessibleInterface*> cells; if (!view()->selectionModel()) return cells; - Q_FOREACH (const QModelIndex &index, view()->selectionModel()->selectedIndexes()) { - cells.append(cell(index)); - } + Q_FOREACH (const QModelIndex &index, view()->selectionModel()->selectedIndexes()) + cells.append(child(logicalIndex(index))); return cells; } @@ -447,7 +403,7 @@ QAccessibleInterface *QAccessibleTable::childAt(int x, int y) const QModelIndex index = view()->indexAt(indexPosition); if (index.isValid()) { - return childFromLogical(logicalIndex(index)); + return child(logicalIndex(index)); } return 0; } @@ -465,7 +421,7 @@ int QAccessibleTable::indexOfChild(const QAccessibleInterface *iface) const { if (!view()->model()) return -1; - QSharedPointer<QAccessibleInterface> parent(iface->parent()); + QAccessibleInterface *parent = iface->parent(); if (parent->object() != view()) return -1; @@ -478,7 +434,7 @@ int QAccessibleTable::indexOfChild(const QAccessibleInterface *iface) const return cell->index + (verticalHeader() ? 1 : 0); } else if (iface->role() == QAccessible::RowHeader){ const QAccessibleTableHeaderCell* cell = static_cast<const QAccessibleTableHeaderCell*>(iface); - return (cell->index + 1) * (view()->model()->rowCount() + 1); + return (cell->index + 1) * (view()->model()->columnCount() + 1); } else if (iface->role() == QAccessible::Pane) { return 0; // corner button } else { @@ -515,9 +471,55 @@ QAccessibleInterface *QAccessibleTable::parent() const return 0; } -QAccessibleInterface *QAccessibleTable::child(int index) const +QAccessibleInterface *QAccessibleTable::child(int logicalIndex) const { - return childFromLogical(index); + if (!view()->model()) + return 0; + + if (childToId.contains(logicalIndex)) { + QAccessible::Id id = childToId.value(logicalIndex); + return QAccessible::accessibleInterface(id); + } + + int vHeader = verticalHeader() ? 1 : 0; + int hHeader = horizontalHeader() ? 1 : 0; + + int columns = view()->model()->columnCount() + vHeader; + + int row = logicalIndex / columns; + int column = logicalIndex % columns; + + QAccessibleInterface *iface = 0; + + if (vHeader) { + if (column == 0) { + if (hHeader && row == 0) { + iface = new QAccessibleTableCornerButton(view()); + } else { + iface = new QAccessibleTableHeaderCell(view(), row - hHeader, Qt::Vertical); + } + } + --column; + } + if (!iface && hHeader) { + if (row == 0) { + iface = new QAccessibleTableHeaderCell(view(), column, Qt::Horizontal); + } + --row; + } + + if (!iface) { + QModelIndex index = view()->model()->index(row, column, view()->rootIndex()); + if (!index.isValid()) { + qWarning() << "QAccessibleTable::child: Invalid index at: " << row << column; + return 0; + } + iface = new QAccessibleTableCell(view(), index, cellRole()); + } + + QAccessible::registerAccessibleInterface(iface); + childToId.insert(logicalIndex, QAccessible::uniqueId(iface)); + return iface; } void *QAccessibleTable::interface_cast(QAccessible::InterfaceType t) @@ -527,6 +529,140 @@ void *QAccessibleTable::interface_cast(QAccessible::InterfaceType t) return 0; } +void QAccessibleTable::modelChange(QAccessibleTableModelChangeEvent *event) +{ + // if there is no cache yet, we don't update anything + if (childToId.isEmpty()) + return; + + switch (event->modelChangeType()) { + case QAccessibleTableModelChangeEvent::ModelReset: + Q_FOREACH (QAccessible::Id id, childToId.values()) + QAccessible::deleteAccessibleInterface(id); + childToId.clear(); + break; + + // rows are inserted: move every row after that + case QAccessibleTableModelChangeEvent::RowsInserted: + case QAccessibleTableModelChangeEvent::ColumnsInserted: { + int newRows = event->lastRow() - event->firstRow() + 1; + int newColumns = event->lastColumn() - event->firstColumn() + 1; + + ChildCache newCache; + ChildCache::ConstIterator iter = childToId.constBegin(); + + while (iter != childToId.constEnd()) { + QAccessible::Id id = iter.value(); + QAccessibleInterface *iface = QAccessible::accessibleInterface(id); + Q_ASSERT(iface); + if (iface->role() == QAccessible::Cell || iface->role() == QAccessible::ListItem) { + Q_ASSERT(iface->tableCellInterface()); + QAccessibleTableCell *cell = static_cast<QAccessibleTableCell*>(iface->tableCellInterface()); + if (event->modelChangeType() == QAccessibleTableModelChangeEvent::RowsInserted + && cell->m_index.row() >= event->firstRow()) { + int newRow = cell->m_index.row() + newRows; + cell->m_index = cell->m_index.sibling(newRow, cell->m_index.column()); + } else if (event->modelChangeType() == QAccessibleTableModelChangeEvent::ColumnsInserted + && cell->m_index.column() >= event->firstColumn()) { + int newColumn = cell->m_index.column() + newColumns; + cell->m_index = cell->m_index.sibling(cell->m_index.row(), newColumn); + } + } else if (event->modelChangeType() == QAccessibleTableModelChangeEvent::RowsInserted + && iface->role() == QAccessible::RowHeader) { + QAccessibleTableHeaderCell *cell = static_cast<QAccessibleTableHeaderCell*>(iface); + if (cell->index >= event->firstRow()) { + cell->index += newRows; + } + } else if (event->modelChangeType() == QAccessibleTableModelChangeEvent::ColumnsInserted + && iface->role() == QAccessible::ColumnHeader) { + QAccessibleTableHeaderCell *cell = static_cast<QAccessibleTableHeaderCell*>(iface); + if (cell->index >= event->firstColumn()) { + cell->index += newColumns; + } + } + if (indexOfChild(iface) >= 0) { + newCache.insert(indexOfChild(iface), id); + } else { + // ### This should really not happen, + // but it might if the view has a root index set. + // This needs to be fixed. + QAccessible::deleteAccessibleInterface(id); + } + ++iter; + } + childToId = newCache; + break; + } + + case QAccessibleTableModelChangeEvent::ColumnsRemoved: + case QAccessibleTableModelChangeEvent::RowsRemoved: { + int deletedColumns = event->lastColumn() - event->firstColumn() + 1; + int deletedRows = event->lastRow() - event->firstRow() + 1; + ChildCache newCache; + ChildCache::ConstIterator iter = childToId.constBegin(); + while (iter != childToId.constEnd()) { + QAccessible::Id id = iter.value(); + QAccessibleInterface *iface = QAccessible::accessibleInterface(id); + Q_ASSERT(iface); + if (iface->role() == QAccessible::Cell || iface->role() == QAccessible::ListItem) { + Q_ASSERT(iface->tableCellInterface()); + QAccessibleTableCell *cell = static_cast<QAccessibleTableCell*>(iface->tableCellInterface()); + if (event->modelChangeType() == QAccessibleTableModelChangeEvent::RowsRemoved) { + if (cell->m_index.row() < event->firstRow()) { + newCache.insert(indexOfChild(cell), id); + } else if (cell->m_index.row() > event->lastRow()) { + int newRow = cell->m_index.row() - deletedRows; + cell->m_index = cell->m_index.sibling(newRow, cell->m_index.column()); + newCache.insert(indexOfChild(cell), id); + } else { + QAccessible::deleteAccessibleInterface(id); + } + } else if (event->modelChangeType() == QAccessibleTableModelChangeEvent::ColumnsRemoved) { + if (cell->m_index.column() < event->firstColumn()) { + newCache.insert(indexOfChild(cell), id); + } else if (cell->m_index.column() > event->lastColumn()) { + int newColumn = cell->m_index.column() - deletedColumns; + cell->m_index = cell->m_index.sibling(cell->m_index.row(), newColumn); + newCache.insert(indexOfChild(cell), id); + } else { + QAccessible::deleteAccessibleInterface(id); + } + } + } else if (event->modelChangeType() == QAccessibleTableModelChangeEvent::RowsRemoved + && iface->role() == QAccessible::RowHeader) { + QAccessibleTableHeaderCell *cell = static_cast<QAccessibleTableHeaderCell*>(iface); + if (cell->index < event->firstRow()) { + newCache.insert(indexOfChild(cell), id); + } else if (cell->index > event->lastRow()) { + cell->index -= deletedRows; + newCache.insert(indexOfChild(cell), id); + } else { + QAccessible::deleteAccessibleInterface(id); + } + } else if (event->modelChangeType() == QAccessibleTableModelChangeEvent::ColumnsRemoved + && iface->role() == QAccessible::ColumnHeader) { + QAccessibleTableHeaderCell *cell = static_cast<QAccessibleTableHeaderCell*>(iface); + if (cell->index < event->firstColumn()) { + newCache.insert(indexOfChild(cell), id); + } else if (cell->index > event->lastColumn()) { + cell->index -= deletedColumns; + newCache.insert(indexOfChild(cell), id); + } else { + QAccessible::deleteAccessibleInterface(id); + } + } + ++iter; + } + childToId = newCache; + break; + } + + case QAccessibleTableModelChangeEvent::DataChanged: + // nothing to do in this case + break; + } +} + // TREE VIEW QModelIndex QAccessibleTree::indexFromLogical(int row, int column) const @@ -578,27 +714,33 @@ int QAccessibleTree::childCount() const } -QAccessibleInterface *QAccessibleTree::child(int index) const +QAccessibleInterface *QAccessibleTree::child(int logicalIndex) const { - if (index < 0 || !view()->model() || !view()->model()->columnCount()) + if (logicalIndex < 0 || !view()->model() || !view()->model()->columnCount()) return 0; - int hHeader = horizontalHeader() ? 1 : 0; - if (hHeader) { + QAccessibleInterface *iface = 0; + int index = logicalIndex; + + if (horizontalHeader()) { if (index < view()->model()->columnCount()) { - return new QAccessibleTableHeaderCell(view(), index, Qt::Horizontal); + iface = new QAccessibleTableHeaderCell(view(), index, Qt::Horizontal); } else { index -= view()->model()->columnCount(); } } - int row = index / view()->model()->columnCount(); - int column = index % view()->model()->columnCount(); - QModelIndex modelIndex = indexFromLogical(row, column); - if (modelIndex.isValid()) { - return cell(modelIndex); + if (!iface) { + int row = index / view()->model()->columnCount(); + int column = index % view()->model()->columnCount(); + QModelIndex modelIndex = indexFromLogical(row, column); + if (!modelIndex.isValid()) + return 0; + iface = new QAccessibleTableCell(view(), modelIndex, cellRole()); } - return 0; + QAccessible::registerAccessibleInterface(iface); + // ### FIXME: get interfaces from the cache instead of re-creating them + return iface; } int QAccessibleTree::rowCount() const @@ -612,7 +754,7 @@ int QAccessibleTree::indexOfChild(const QAccessibleInterface *iface) const { if (!view()->model()) return -1; - QSharedPointer<QAccessibleInterface> parent(iface->parent()); + QAccessibleInterface *parent = iface->parent(); if (parent->object() != view()) return -1; @@ -624,12 +766,10 @@ int QAccessibleTree::indexOfChild(const QAccessibleInterface *iface) const int column = cell->m_index.column(); int index = row * view()->model()->columnCount() + column; - //qDebug() << "QAccessibleTree::indexOfChild r " << row << " c " << column << "index " << index; Q_ASSERT(index >= treeView->model()->columnCount()); return index; } else if (iface->role() == QAccessible::ColumnHeader){ const QAccessibleTableHeaderCell* cell = static_cast<const QAccessibleTableHeaderCell*>(iface); - //qDebug() << "QAccessibleTree::indexOfChild header " << cell->index; return cell->index; } else { qWarning() << "WARNING QAccessibleTable::indexOfChild invalid child" @@ -646,7 +786,11 @@ QAccessibleInterface *QAccessibleTree::cellAt(int row, int column) const qWarning() << "Requested invalid tree cell: " << row << column; return 0; } - return new QAccessibleTableCell(view(), index, cellRole()); + const QTreeView *treeView = qobject_cast<const QTreeView*>(view()); + Q_ASSERT(treeView); + int logicalIndex = treeView->d_func()->accessibleTable2Index(index); + + return child(logicalIndex); // FIXME ### new QAccessibleTableCell(view(), index, cellRole()); } QString QAccessibleTree::rowDescription(int) const @@ -717,6 +861,7 @@ QList<QAccessibleInterface*> QAccessibleTableCell::rowHeaderCells() const { QList<QAccessibleInterface*> headerCell; if (verticalHeader()) { + // FIXME headerCell.append(new QAccessibleTableHeaderCell(view, m_index.row(), Qt::Vertical)); } return headerCell; @@ -726,6 +871,7 @@ QList<QAccessibleInterface*> QAccessibleTableCell::columnHeaderCells() const { QList<QAccessibleInterface*> headerCell; if (horizontalHeader()) { + // FIXME headerCell.append(new QAccessibleTableHeaderCell(view, m_index.column(), Qt::Horizontal)); } return headerCell; @@ -808,18 +954,18 @@ void QAccessibleTableCell::selectCell() QAbstractItemView::SelectionMode selectionMode = view->selectionMode(); if (!m_index.isValid() || (selectionMode == QAbstractItemView::NoSelection)) return; - - QSharedPointer<QAccessibleTableInterface> cellTable(table()->tableInterface()); + Q_ASSERT(table()); + QAccessibleTableInterface *cellTable = table()->tableInterface(); switch (view->selectionBehavior()) { case QAbstractItemView::SelectItems: break; case QAbstractItemView::SelectColumns: - if (cellTable.data()) + if (cellTable) cellTable->selectColumn(m_index.column()); return; case QAbstractItemView::SelectRows: - if (cellTable.data()) + if (cellTable) cellTable->selectRow(m_index.row()); return; } @@ -838,17 +984,17 @@ void QAccessibleTableCell::unselectCell() if (!m_index.isValid() || (selectionMode & QAbstractItemView::NoSelection)) return; - QSharedPointer<QAccessibleTableInterface> cellTable(table()->tableInterface()); + QAccessibleTableInterface *cellTable = table()->tableInterface(); switch (view->selectionBehavior()) { case QAbstractItemView::SelectItems: break; case QAbstractItemView::SelectColumns: - if (cellTable.data()) + if (cellTable) cellTable->unselectColumn(m_index.column()); return; case QAbstractItemView::SelectRows: - if (cellTable.data()) + if (cellTable) cellTable->unselectRow(m_index.row()); return; } @@ -962,10 +1108,7 @@ bool QAccessibleTableCell::isValid() const QAccessibleInterface *QAccessibleTableCell::parent() const { - if (m_role == QAccessible::TreeItem) - return new QAccessibleTree(view); - - return new QAccessibleTable(view); + return QAccessible::queryAccessibleInterface(view); } QAccessibleInterface *QAccessibleTableCell::child(int) const @@ -1051,11 +1194,7 @@ bool QAccessibleTableHeaderCell::isValid() const QAccessibleInterface *QAccessibleTableHeaderCell::parent() const { -#ifndef QT_NO_TREEVIEW - if (qobject_cast<const QTreeView*>(view)) - return new QAccessibleTree(view); -#endif - return new QAccessibleTable(view); + return QAccessible::queryAccessibleInterface(view); } QAccessibleInterface *QAccessibleTableHeaderCell::child(int) const diff --git a/src/plugins/accessible/widgets/itemviews.h b/src/plugins/accessible/widgets/itemviews.h index af885fe6c1..09dacde7a2 100644 --- a/src/plugins/accessible/widgets/itemviews.h +++ b/src/plugins/accessible/widgets/itemviews.h @@ -65,8 +65,6 @@ public: explicit QAccessibleTable(QWidget *w); bool isValid() const; - virtual ~QAccessibleTable(); - QAccessible::Role role() const; QAccessible::State state() const; QString text(QAccessible::Text t) const; @@ -106,9 +104,9 @@ public: QAbstractItemView *view() const; -protected: - inline QAccessibleTableCell *cell(const QModelIndex &index) const; + void modelChange(QAccessibleTableModelChangeEvent *event); +protected: inline QAccessible::Role cellRole() const { switch (m_role) { case QAccessible::List: @@ -125,11 +123,16 @@ protected: QHeaderView *horizontalHeader() const; QHeaderView *verticalHeader() const; + + // maybe vector + typedef QHash<int, QAccessible::Id> ChildCache; + mutable ChildCache childToId; + + virtual ~QAccessibleTable(); + private: // the child index for a model index inline int logicalIndex(const QModelIndex &index) const; - // the model index from the child index - QAccessibleInterface *childFromLogical(int logicalIndex) const; QAccessible::Role m_role; }; @@ -140,7 +143,6 @@ public: : QAccessibleTable(w) {} - virtual ~QAccessibleTree() {} QAccessibleInterface *childAt(int x, int y) const; int childCount() const; @@ -158,6 +160,8 @@ public: private: QModelIndex indexFromLogical(int row, int column = 0) const; + + inline int logicalIndex(const QModelIndex &index) const; }; class QAccessibleTableCell: public QAccessibleInterface, public QAccessibleTableCellInterface, public QAccessibleActionInterface @@ -236,7 +240,7 @@ public: QAccessibleInterface *child(int index) const; private: - QAbstractItemView *view; + QPointer<QAbstractItemView> view; int index; Qt::Orientation orientation; @@ -273,8 +277,9 @@ public: QAccessibleInterface *child(int) const { return 0; } + private: - QAbstractItemView *view; + QPointer<QAbstractItemView> view; }; diff --git a/src/plugins/accessible/widgets/main.cpp b/src/plugins/accessible/widgets/main.cpp index ade4979256..686a90ca96 100644 --- a/src/plugins/accessible/widgets/main.cpp +++ b/src/plugins/accessible/widgets/main.cpp @@ -177,14 +177,6 @@ QAccessibleInterface *AccessibleFactory::create(const QString &classname, QObjec } else if (classname == QLatin1String("QTableView") || classname == QLatin1String("QListView")) { iface = new QAccessibleTable(widget); // ### This should be cleaned up. We return the parent for the scrollarea to hide it. - } else if (classname == QLatin1String("QWidget") - && widget->objectName() == QLatin1String("qt_scrollarea_viewport") - && qobject_cast<QAbstractItemView*>(widget->parentWidget())) { - if (qobject_cast<const QTreeView*>(widget->parentWidget())) { - iface = new QAccessibleTree(widget->parentWidget()); - } else { - iface = new QAccessibleTable(widget->parentWidget()); - } #endif // QT_NO_ITEMVIEWS #ifndef QT_NO_TABBAR } else if (classname == QLatin1String("QTabBar")) { diff --git a/src/plugins/accessible/widgets/qaccessiblemenu.cpp b/src/plugins/accessible/widgets/qaccessiblemenu.cpp index e467ef50bd..f248e6d05e 100644 --- a/src/plugins/accessible/widgets/qaccessiblemenu.cpp +++ b/src/plugins/accessible/widgets/qaccessiblemenu.cpp @@ -55,6 +55,16 @@ QT_BEGIN_NAMESPACE QString Q_GUI_EXPORT qt_accStripAmp(const QString &text); QString Q_GUI_EXPORT qt_accHotKey(const QString &text); +QAccessibleInterface *getOrCreateMenu(QWidget *menu, QAction *action) +{ + QAccessibleInterface *iface = QAccessible::queryAccessibleInterface(action); + if (!iface) { + iface = new QAccessibleMenuItem(menu, action); + QAccessible::registerAccessibleInterface(iface); + } + return iface; +} + QAccessibleMenu::QAccessibleMenu(QWidget *w) : QAccessibleWidget(w) { @@ -76,7 +86,7 @@ QAccessibleInterface *QAccessibleMenu::childAt(int x, int y) const QAction *act = menu()->actionAt(menu()->mapFromGlobal(QPoint(x,y))); if(act && act->isSeparator()) act = 0; - return act ? new QAccessibleMenuItem(menu(), act) : 0; + return act ? getOrCreateMenu(menu(), act) : 0; } QString QAccessibleMenu::text(QAccessible::Text t) const @@ -98,7 +108,7 @@ QAccessible::Role QAccessibleMenu::role() const QAccessibleInterface *QAccessibleMenu::child(int index) const { if (index < childCount()) - return new QAccessibleMenuItem(menu(), menu()->actions().at(index)); + return getOrCreateMenu(menu(), menu()->actions().at(index)); return 0; } @@ -111,7 +121,7 @@ QAccessibleInterface *QAccessibleMenu::parent() const foreach (QWidget *w, parentCandidates) { if (qobject_cast<QMenu*>(w) || qobject_cast<QMenuBar*>(w)) { if (w->actions().indexOf(menuAction) != -1) - return new QAccessibleMenuItem(w, menuAction); + return getOrCreateMenu(w, menuAction); } } } @@ -146,8 +156,9 @@ int QAccessibleMenuBar::childCount() const QAccessibleInterface *QAccessibleMenuBar::child(int index) const { - if (index < childCount()) - return new QAccessibleMenuItem(menuBar(), menuBar()->actions().at(index)); + if (index < childCount()) { + return getOrCreateMenu(menuBar(), menuBar()->actions().at(index)); + } return 0; } @@ -177,7 +188,6 @@ QAccessibleInterface *QAccessibleMenuItem::childAt(int x, int y ) const if (childInterface->rect().contains(x,y)) { return childInterface; } - delete childInterface; } return 0; } @@ -207,7 +217,7 @@ QAccessibleInterface *QAccessibleMenuItem::parent() const QAccessibleInterface *QAccessibleMenuItem::child(int index) const { if (index == 0 && action()->menu()) - return new QAccessibleMenu(action()->menu()); + return QAccessible::queryAccessibleInterface(action()->menu()); return 0; } diff --git a/src/plugins/accessible/widgets/qaccessiblewidgets.cpp b/src/plugins/accessible/widgets/qaccessiblewidgets.cpp index b5ee4a6046..751a722bb8 100644 --- a/src/plugins/accessible/widgets/qaccessiblewidgets.cpp +++ b/src/plugins/accessible/widgets/qaccessiblewidgets.cpp @@ -718,7 +718,6 @@ QAccessibleInterface *QAccessibleTitleBar::childAt(int x, int y) const if (childIface->rect().contains(x,y)) { return childIface; } - delete childIface; } return 0; } diff --git a/src/plugins/platforms/cocoa/cocoa.pro b/src/plugins/platforms/cocoa/cocoa.pro index 6ed26f9e6c..66c4e3c49c 100644 --- a/src/plugins/platforms/cocoa/cocoa.pro +++ b/src/plugins/platforms/cocoa/cocoa.pro @@ -102,8 +102,5 @@ OTHER_FILES += cocoa.json # DEFINES += QT_COCOA_ENABLE_ACCESSIBILITY_INSPECTOR # include ($$PWD/../../../../util/accessibilityinspector/accessibilityinspector.pri) -# Accessibility is currently unstable and disabled. -DEFINES += QT_NO_COCOA_ACCESSIBILITY - # Window debug support #DEFINES += QT_COCOA_ENABLE_WINDOW_DEBUG diff --git a/src/plugins/platforms/cocoa/qcocoaaccessibility.h b/src/plugins/platforms/cocoa/qcocoaaccessibility.h index 0f1f96814f..3f0367d36a 100644 --- a/src/plugins/platforms/cocoa/qcocoaaccessibility.h +++ b/src/plugins/platforms/cocoa/qcocoaaccessibility.h @@ -44,9 +44,6 @@ #include <Cocoa/Cocoa.h> #include <QtGui> - -#ifndef QT_NO_COCOA_ACCESSIBILITY - #include <qpa/qplatformaccessibility.h> class QCococaAccessibility : public QPlatformAccessibility @@ -81,7 +78,7 @@ namespace QCocoaAccessible { */ NSString *macRole(QAccessibleInterface *interface); -bool shouldBeIgnrored(QAccessibleInterface *interface); +bool shouldBeIgnored(QAccessibleInterface *interface); NSString *getTranslatedAction(const QString &qtAction); NSMutableArray *createTranslatedActionsList(const QStringList &qtActions); QString translateAction(NSString *nsAction); @@ -90,6 +87,4 @@ id getValueAttribute(QAccessibleInterface *interface); } -#endif // QT_NO_COCOA_ACCESSIBILITY - #endif diff --git a/src/plugins/platforms/cocoa/qcocoaaccessibility.mm b/src/plugins/platforms/cocoa/qcocoaaccessibility.mm index adeb423cf9..34192e85b0 100644 --- a/src/plugins/platforms/cocoa/qcocoaaccessibility.mm +++ b/src/plugins/platforms/cocoa/qcocoaaccessibility.mm @@ -44,8 +44,6 @@ #include <QtGui/private/qaccessible2_p.h> #include <private/qcore_mac_p.h> -#ifndef QT_NO_COCOA_ACCESSIBILITY - QCococaAccessibility::QCococaAccessibility() { @@ -62,7 +60,7 @@ void QCococaAccessibility::notifyAccessibilityUpdate(QAccessibleEvent *event) if (!object) return; - QAccessibleInterface *interface = QAccessible::queryAccessibleInterface(object); + QAccessibleInterface *interface = event->accessibleInterface(); if (!interface) return; @@ -71,13 +69,11 @@ void QCococaAccessibility::notifyAccessibilityUpdate(QAccessibleEvent *event) case QAccessible::TextInserted : case QAccessible::TextRemoved : case QAccessible::TextUpdated : { - QCocoaAccessibleElement *element = [QCocoaAccessibleElement createElementWithInterface : interface parent : nil]; + QCocoaAccessibleElement *element = [QCocoaAccessibleElement createElementWithId : QAccessible::uniqueId(interface) parent : nil]; [element autorelease]; NSAccessibilityPostNotification(element, NSAccessibilityValueChangedNotification); break; } - - default: - delete interface; + default: break; } } @@ -178,7 +174,7 @@ NSString *macRole(QAccessibleInterface *interface) the elements are still present in the accessibility tree but is not used by the screen reader. */ -bool shouldBeIgnrored(QAccessibleInterface *interface) +bool shouldBeIgnored(QAccessibleInterface *interface) { // Mac accessibility does not have an attribute that corresponds to the Invisible/Offscreen // state. Ignore interfaces with those flags set. @@ -280,6 +276,7 @@ QString translateAction(NSString *nsAction) bool hasValueAttribute(QAccessibleInterface *interface) { + Q_ASSERT(interface); const QAccessible::Role qtrole = interface->role(); if (qtrole == QAccessible::EditableText || interface->valueInterface()) { @@ -318,5 +315,3 @@ id getValueAttribute(QAccessibleInterface *interface) } } // namespace QCocoaAccessible - -#endif // QT_NO_COCOA_ACCESSIBILITY diff --git a/src/plugins/platforms/cocoa/qcocoaaccessibilityelement.h b/src/plugins/platforms/cocoa/qcocoaaccessibilityelement.h index 3b1fbe042d..c207cbee2d 100644 --- a/src/plugins/platforms/cocoa/qcocoaaccessibilityelement.h +++ b/src/plugins/platforms/cocoa/qcocoaaccessibilityelement.h @@ -46,22 +46,20 @@ #import <Cocoa/Cocoa.h> #import <AppKit/NSAccessibility.h> -#ifndef QT_NO_COCOA_ACCESSIBILITY +#import <qaccessible.h> @class QCocoaAccessibleElement; @interface QCocoaAccessibleElement : NSObject { NSString *role; - NSObject * parent; - void *accessibleInterface; + NSObject *parent; + QAccessible::Id axid; } -- (id)initWithInterface:(void *)anQAccessibleInterface parent:(id)aParent; -+ (QCocoaAccessibleElement *)createElementWithInterface:(void *)anQAccessibleInterface parent:(id)aParent; +- (id)initWithId:(QAccessible::Id)anId parent:(id)aParent; ++ (QCocoaAccessibleElement *)createElementWithId:(QAccessible::Id)anId parent:(id)aParent; @end -#endif // QT_NO_COCOA_ACCESSIBILITY - #endif diff --git a/src/plugins/platforms/cocoa/qcocoaaccessibilityelement.mm b/src/plugins/platforms/cocoa/qcocoaaccessibilityelement.mm index df496a413b..1d6797e51a 100644 --- a/src/plugins/platforms/cocoa/qcocoaaccessibilityelement.mm +++ b/src/plugins/platforms/cocoa/qcocoaaccessibilityelement.mm @@ -47,48 +47,43 @@ #import <AppKit/NSAccessibility.h> -#ifndef QT_NO_COCOA_ACCESSIBILITY - -static QAccessibleInterface *acast(void *ptr) -{ - return reinterpret_cast<QAccessibleInterface *>(ptr); -} - @implementation QCocoaAccessibleElement -- (id)initWithInterface:(void *)anQAccessibleInterface parent:(id)aParent +- (id)initWithId:(QAccessible::Id)anId parent:(id)aParent { + Q_ASSERT((int)anId < 0); self = [super init]; if (self) { - accessibleInterface = anQAccessibleInterface; - role = QCocoaAccessible::macRole(acast(accessibleInterface)); + axid = anId; + QAccessibleInterface *iface = QAccessible::accessibleInterface(axid); + Q_ASSERT(iface); + role = QCocoaAccessible::macRole(iface); parent = aParent; } return self; } -+ (QCocoaAccessibleElement *)createElementWithInterface:(void *)anQAccessibleInterface parent:(id)aParent ++ (QCocoaAccessibleElement *)createElementWithId:(QAccessible::Id)anId parent:(id)aParent { - return [[self alloc] initWithInterface:anQAccessibleInterface parent:aParent]; + return [[self alloc] initWithId:anId parent:aParent]; } - (void)dealloc { [super dealloc]; - delete acast(accessibleInterface); } - (BOOL)isEqual:(id)object { if ([object isKindOfClass:[QCocoaAccessibleElement class]]) { QCocoaAccessibleElement *other = object; - return acast(other->accessibleInterface)->object() == acast(accessibleInterface)->object(); + return other->axid == axid; } else { return NO; } } - (NSUInteger)hash { - return qHash(acast(accessibleInterface)->object()); + return axid; } // @@ -99,6 +94,11 @@ static QAccessibleInterface *acast(void *ptr) - (NSArray *)accessibilityAttributeNames { static NSArray *defaultAttributes = nil; + + QAccessibleInterface *iface = QAccessible::accessibleInterface(axid); + if (!iface) + return defaultAttributes; + if (defaultAttributes == nil) { defaultAttributes = [[NSArray alloc] initWithObjects: NSAccessibilityRoleAttribute, @@ -118,7 +118,7 @@ static QAccessibleInterface *acast(void *ptr) NSMutableArray *attributes = [[NSMutableArray alloc] initWithCapacity : [defaultAttributes count]]; [attributes addObjectsFromArray : defaultAttributes]; - if (QCocoaAccessible::hasValueAttribute(acast(accessibleInterface))) { + if (QCocoaAccessible::hasValueAttribute(iface)) { [attributes addObject : NSAccessibilityValueAttribute]; } @@ -126,22 +126,33 @@ static QAccessibleInterface *acast(void *ptr) } - (id)accessibilityAttributeValue:(NSString *)attribute { + QAccessibleInterface *iface = QAccessible::accessibleInterface(axid); + if (!iface) { + qWarning() << "Called attribute on invalid object: " << axid; + return nil; + } + if ([attribute isEqualToString:NSAccessibilityRoleAttribute]) { return role; } else if ([attribute isEqualToString:NSAccessibilityRoleDescriptionAttribute]) { return NSAccessibilityRoleDescription(role, nil); } else if ([attribute isEqualToString:NSAccessibilityChildrenAttribute]) { - int numKids = acast(accessibleInterface)->childCount(); + + int numKids = iface->childCount(); + // qDebug() << "Children for: " << axid << iface << " are: " << numKids; NSMutableArray *kids = [NSMutableArray arrayWithCapacity:numKids]; for (int i = 0; i < numKids; ++i) { - QAccessibleInterface *childInterface = acast(accessibleInterface)->child(i); - QCocoaAccessibleElement *element = [QCocoaAccessibleElement createElementWithInterface:(void*)childInterface parent:self]; + QAccessibleInterface *child = iface->child(i); + Q_ASSERT(child); + QAccessible::Id childId = QAccessible::uniqueId(child); + //qDebug() << " kid: " << childId << child; + QCocoaAccessibleElement *element = [QCocoaAccessibleElement createElementWithId:childId parent:self]; [kids addObject: element]; [element release]; } - return kids; + } else if ([attribute isEqualToString:NSAccessibilityFocusedAttribute]) { // Just check if the app thinks we're focused. id focusedElement = [NSApp accessibilityAttributeValue:NSAccessibilityFocusedUIElementAttribute]; @@ -155,23 +166,23 @@ static QAccessibleInterface *acast(void *ptr) // We're in the same top level element as our parent. return [parent accessibilityAttributeValue:NSAccessibilityTopLevelUIElementAttribute]; } else if ([attribute isEqualToString:NSAccessibilityPositionAttribute]) { - QPoint qtPosition = acast(accessibleInterface)->rect().topLeft(); - QSize qtSize = acast(accessibleInterface)->rect().size(); + QPoint qtPosition = iface->rect().topLeft(); + QSize qtSize = iface->rect().size(); return [NSValue valueWithPoint: NSMakePoint(qtPosition.x(), qt_mac_flipYCoordinate(qtPosition.y() + qtSize.height()))]; } else if ([attribute isEqualToString:NSAccessibilitySizeAttribute]) { - QSize qtSize = acast(accessibleInterface)->rect().size(); + QSize qtSize = iface->rect().size(); return [NSValue valueWithSize: NSMakeSize(qtSize.width(), qtSize.height())]; } else if ([attribute isEqualToString:NSAccessibilityDescriptionAttribute]) { - return QCFString::toNSString(acast(accessibleInterface)->text(QAccessible::Name)); + return QCFString::toNSString(iface->text(QAccessible::Name)); } else if ([attribute isEqualToString:NSAccessibilityEnabledAttribute]) { - return [NSNumber numberWithBool:!acast(accessibleInterface)->state().disabled]; + return [NSNumber numberWithBool:!iface->state().disabled]; } else if ([attribute isEqualToString:NSAccessibilityValueAttribute]) { // VoiceOver asks for the value attribute for all elements. Return nil // if we don't want the element to have a value attribute. - if (!QCocoaAccessible::hasValueAttribute(acast(accessibleInterface))) + if (!QCocoaAccessible::hasValueAttribute(iface)) return nil; - return QCocoaAccessible::getValueAttribute(acast(accessibleInterface)); + return QCocoaAccessible::getValueAttribute(iface); } return nil; @@ -196,8 +207,11 @@ static QAccessibleInterface *acast(void *ptr) - (NSArray *)accessibilityActionNames { NSMutableArray * nsActions = [NSMutableArray new]; + QAccessibleInterface *iface = QAccessible::accessibleInterface(axid); + if (!iface) + return nsActions; - QAccessibleActionInterface *actionInterface = acast(accessibleInterface)->actionInterface(); + QAccessibleActionInterface *actionInterface = iface->actionInterface(); if (actionInterface) { QStringList supportedActionNames = actionInterface->actionNames(); @@ -212,48 +226,58 @@ static QAccessibleInterface *acast(void *ptr) } - (NSString *)accessibilityActionDescription:(NSString *)action { - QAccessibleActionInterface *actionInterface = acast(accessibleInterface)->actionInterface(); - QString qtAction = QCocoaAccessible::translateAction(action); + QAccessibleInterface *iface = QAccessible::accessibleInterface(axid); + if (!iface) + return nil; // FIXME is that the right return type?? + QAccessibleActionInterface *actionInterface = iface->actionInterface(); + if (actionInterface) { + QString qtAction = QCocoaAccessible::translateAction(action); - // Return a description from the action interface if this action is not known to the OS. - if (qtAction.isEmpty()) { - QString description = actionInterface->localizedActionDescription(qtAction); - return QCFString::toNSString(description); + // Return a description from the action interface if this action is not known to the OS. + if (qtAction.isEmpty()) { + QString description = actionInterface->localizedActionDescription(qtAction); + return QCFString::toNSString(description); + } } return NSAccessibilityActionDescription(action); } - (void)accessibilityPerformAction:(NSString *)action { - QAccessibleActionInterface *actionInterface = acast(accessibleInterface)->actionInterface(); - if (actionInterface) { - actionInterface->doAction(QCocoaAccessible::translateAction(action)); + QAccessibleInterface *iface = QAccessible::accessibleInterface(axid); + if (iface) { + QAccessibleActionInterface *actionInterface = iface->actionInterface(); + if (actionInterface) { + actionInterface->doAction(QCocoaAccessible::translateAction(action)); + } } } // misc - (BOOL)accessibilityIsIgnored { - return QCocoaAccessible::shouldBeIgnrored(acast(accessibleInterface)); + return false; //QCocoaAccessible::shouldBeIgnored(QAccessible::accessibleInterface(id)); } - (id)accessibilityHitTest:(NSPoint)point { - - if (!accessibleInterface) - return NSAccessibilityUnignoredAncestor(self); - - if (!acast(accessibleInterface)->isValid()) + QAccessibleInterface *iface = QAccessible::accessibleInterface(axid); + if (!iface || !iface->isValid()) { +// qDebug() << "Hit test: INVALID"; return NSAccessibilityUnignoredAncestor(self); + } - QAccessibleInterface *childInterface = acast(accessibleInterface)->childAt(point.x, qt_mac_flipYCoordinate(point.y)); + QAccessibleInterface *childInterface = iface->childAt(point.x, qt_mac_flipYCoordinate(point.y)); // No child found, meaning we hit this element. if (!childInterface) { - return NSAccessibilityUnignoredAncestor(self); +// qDebug() << "Hit test returns: " << id << iface; + return self; + //return NSAccessibilityUnignoredAncestor(self); } + QAccessible::Id childId = QAccessible::uniqueId(childInterface); // hit a child, forward to child accessible interface. - QCocoaAccessibleElement *accessibleElement = [QCocoaAccessibleElement createElementWithInterface:childInterface parent:self]; + QCocoaAccessibleElement *accessibleElement = [QCocoaAccessibleElement createElementWithId:childId parent:self]; [accessibleElement autorelease]; return [accessibleElement accessibilityHitTest:point]; @@ -264,6 +288,3 @@ static QAccessibleInterface *acast(void *ptr) } @end - -#endif // QT_NO_COCOA_ACCESSIBILITY - diff --git a/src/plugins/platforms/cocoa/qcocoaintegration.h b/src/plugins/platforms/cocoa/qcocoaintegration.h index d667ac4a86..6e690dd51e 100644 --- a/src/plugins/platforms/cocoa/qcocoaintegration.h +++ b/src/plugins/platforms/cocoa/qcocoaintegration.h @@ -132,7 +132,7 @@ private: QAbstractEventDispatcher *mEventDispatcher; QScopedPointer<QPlatformInputContext> mInputContext; -#ifndef QT_NO_COCOA_ACCESSIBILITY +#ifndef QT_NO_ACCESSIBILITY QScopedPointer<QPlatformAccessibility> mAccessibility; #endif QScopedPointer<QPlatformTheme> mPlatformTheme; diff --git a/src/plugins/platforms/cocoa/qcocoaintegration.mm b/src/plugins/platforms/cocoa/qcocoaintegration.mm index 3312de6e3f..e2d867e623 100644 --- a/src/plugins/platforms/cocoa/qcocoaintegration.mm +++ b/src/plugins/platforms/cocoa/qcocoaintegration.mm @@ -216,7 +216,7 @@ QCocoaIntegration::QCocoaIntegration() : mFontDb(new QCoreTextFontDatabase()) , mEventDispatcher(new QCocoaEventDispatcher()) , mInputContext(new QCocoaInputContext) -#ifndef QT_NO_COCOA_ACCESSIBILITY +#ifndef QT_NO_ACCESSIBILITY , mAccessibility(new QCococaAccessibility) #endif , mCocoaClipboard(new QCocoaClipboard) @@ -395,7 +395,7 @@ QPlatformInputContext *QCocoaIntegration::inputContext() const QPlatformAccessibility *QCocoaIntegration::accessibility() const { -#ifndef QT_NO_COCOA_ACCESSIBILITY +#ifndef QT_NO_ACCESSIBILITY return mAccessibility.data(); #else return 0; diff --git a/src/plugins/platforms/cocoa/qnsviewaccessibility.mm b/src/plugins/platforms/cocoa/qnsviewaccessibility.mm index e05ffbe343..e3b8cf6532 100644 --- a/src/plugins/platforms/cocoa/qnsviewaccessibility.mm +++ b/src/plugins/platforms/cocoa/qnsviewaccessibility.mm @@ -51,8 +51,6 @@ #import <AppKit/NSAccessibility.h> -#ifndef QT_NO_COCOA_ACCESSIBILITY - @implementation QNSView (QNSViewAccessibility) // The QNSView is a container that the user does not interact directly with: @@ -77,7 +75,10 @@ int numKids = m_accessibleRoot->childCount(); NSMutableArray *kids = [NSMutableArray arrayWithCapacity:numKids]; for (int i = 0; i < numKids; ++i) { - QCocoaAccessibleElement *element = [QCocoaAccessibleElement createElementWithInterface: m_accessibleRoot->child(i) parent:self ]; + QAccessibleInterface *child = m_accessibleRoot->child(i); + Q_ASSERT(child); + QAccessible::Id childAxid = QAccessible::uniqueId(child); + QCocoaAccessibleElement *element = [QCocoaAccessibleElement createElementWithId:childAxid parent:self]; [kids addObject: element]; [element release]; } @@ -99,12 +100,10 @@ } // Hit a child, forward to child accessible interface. - - QCocoaAccessibleElement *accessibleElement = [QCocoaAccessibleElement createElementWithInterface: childInterface parent:self ]; + QAccessible::Id childAxid = QAccessible::uniqueId(childInterface); + QCocoaAccessibleElement *accessibleElement = [QCocoaAccessibleElement createElementWithId:childAxid parent:self ]; [accessibleElement autorelease]; return [accessibleElement accessibilityHitTest:point]; } @end - -#endif // QT_NO_COCOA_ACCESSIBILITY diff --git a/src/plugins/platforms/windows/accessible/iaccessible2.cpp b/src/plugins/platforms/windows/accessible/iaccessible2.cpp index 44e715d0ce..b1afd7aca3 100644 --- a/src/plugins/platforms/windows/accessible/iaccessible2.cpp +++ b/src/plugins/platforms/windows/accessible/iaccessible2.cpp @@ -230,6 +230,10 @@ HRESULT STDMETHODCALLTYPE AccessibleRelation::get_targets( **************************************************************/ HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::QueryInterface(REFIID id, LPVOID *iface) { + QAccessibleInterface *accessible = accessibleInterface(); + if (!accessible) + return E_NOINTERFACE; + HRESULT hr = QWindowsMsaaAccessible::QueryInterface(id, iface); if (!SUCCEEDED(hr)) { if (id == IID_IServiceProvider) { @@ -301,10 +305,11 @@ ULONG STDMETHODCALLTYPE QWindowsIA2Accessible::Release() **************************************************************/ HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_nRelations(long *nRelations) { + QAccessibleInterface *accessible = accessibleInterface(); accessibleDebugClientCalls(accessible); if (!nRelations) return E_INVALIDARG; - if (!accessible->isValid()) + if (!accessible) return E_FAIL; return getRelationsHelper(0, 0, 0, nRelations); @@ -312,10 +317,11 @@ HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_nRelations(long *nRelations HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_relation(long relationIndex, IAccessibleRelation **relation) { + QAccessibleInterface *accessible = accessibleInterface(); accessibleDebugClientCalls(accessible); if (!relation) return E_INVALIDARG; - if (!accessible->isValid()) + if (!accessible) return E_FAIL; return getRelationsHelper(relation, relationIndex, 1); @@ -330,8 +336,9 @@ HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_relations(long maxRelations IAccessibleRelation **relations, long *nRelations) { + QAccessibleInterface *accessible = accessibleInterface(); accessibleDebugClientCalls(accessible); - if (!accessible->isValid()) + if (!accessible) return E_FAIL; return getRelationsHelper(relations, 0, maxRelations, nRelations); @@ -340,8 +347,9 @@ HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_relations(long maxRelations HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::role(long *ia2role) { + QAccessibleInterface *accessible = accessibleInterface(); accessibleDebugClientCalls(accessible); - if (!accessible->isValid()) + if (!accessible) return E_FAIL; long r = accessible->role(); @@ -386,8 +394,9 @@ HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_groupPosition(long *groupLe HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_states(AccessibleStates *states) { + QAccessibleInterface *accessible = accessibleInterface(); accessibleDebugClientCalls(accessible); - if (!accessible->isValid()) + if (!accessible) return E_FAIL; if (!states) return E_POINTER; @@ -462,23 +471,23 @@ HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_localizedExtendedStates(lon HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_uniqueID(long *outUniqueID) { + QAccessibleInterface *accessible = accessibleInterface(); accessibleDebugClientCalls(accessible); - if (!accessible->isValid()) + if (!accessible) return E_FAIL; - // ### FIXME SERIOUSLY, NOT A STABLE SOLUTION IF NODES ARE DELETED ETC - // Return 0 if no object and no parent. This is really an error case. - uint uid = uniqueID(); - accessibleDebug("uniqueID: %08x", uid); - *outUniqueID = (long)uid; - return uid ? S_OK : S_FALSE; + accessibleDebug("uniqueID: %08x", id); + + *outUniqueID = (long)id; + return int(id) < 0 ? S_OK : S_FALSE; } HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_windowHandle(HWND *windowHandle) { + QAccessibleInterface *accessible = accessibleInterface(); accessibleDebugClientCalls(accessible); - if (!accessible->isValid()) + if (!accessible) return E_FAIL; return GetWindow(windowHandle); } @@ -486,8 +495,9 @@ HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_windowHandle(HWND *windowHa HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_indexInParent(long *indexInParent) { + QAccessibleInterface *accessible = accessibleInterface(); accessibleDebugClientCalls(accessible); - if (!accessible->isValid()) + if (!accessible) return E_FAIL; if (!indexInParent) return E_INVALIDARG; @@ -497,7 +507,6 @@ HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_indexInParent(long *indexIn return S_FALSE; } int indexOfChild = par->indexOfChild(accessible); - delete par; Q_ASSERT(indexOfChild >= 0); *indexInParent = indexOfChild; return S_OK; @@ -505,8 +514,9 @@ HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_indexInParent(long *indexIn HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_locale(IA2Locale *locale) { + QAccessibleInterface *accessible = accessibleInterface(); accessibleDebugClientCalls(accessible); - if (!accessible->isValid()) + if (!accessible) return E_FAIL; IA2Locale res; QLocale l; @@ -519,8 +529,9 @@ HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_locale(IA2Locale *locale) HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_attributes(BSTR *attributes) { + QAccessibleInterface *accessible = accessibleInterface(); accessibleDebugClientCalls(accessible); - if (!accessible->isValid()) + if (!accessible) return E_FAIL; *attributes = 0;//QStringToBSTR(QString()); return S_FALSE; @@ -531,8 +542,9 @@ HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_attributes(BSTR *attributes **************************************************************/ HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::nActions(long *nActions) { + QAccessibleInterface *accessible = accessibleInterface(); accessibleDebugClientCalls(accessible); - if (!accessible->isValid()) + if (!accessible) return E_FAIL; *nActions = 0; @@ -543,8 +555,9 @@ HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::nActions(long *nActions) HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::doAction(long actionIndex) { + QAccessibleInterface *accessible = accessibleInterface(); accessibleDebugClientCalls(accessible); - if (!accessible->isValid()) + if (!accessible) return E_FAIL; if (QAccessibleActionInterface *actionIface = actionInterface()) { const QStringList actionNames = actionIface->actionNames(); @@ -559,8 +572,9 @@ HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::doAction(long actionIndex) HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_description(long actionIndex, BSTR *description) { + QAccessibleInterface *accessible = accessibleInterface(); accessibleDebugClientCalls(accessible); - if (!accessible->isValid()) + if (!accessible) return E_FAIL; *description = 0; if (QAccessibleActionInterface *actionIface = actionInterface()) { @@ -575,8 +589,9 @@ HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_description(long actionInde HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_keyBinding(long actionIndex, long nMaxBindings, BSTR **keyBindings, long *nBindings) { + QAccessibleInterface *accessible = accessibleInterface(); accessibleDebugClientCalls(accessible); - if (!accessible->isValid()) + if (!accessible) return E_FAIL; Q_UNUSED(nMaxBindings); BSTR *arrayOfBindingsToReturn = 0; @@ -603,8 +618,9 @@ HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_keyBinding(long actionIndex HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_name(long actionIndex, BSTR *name) { + QAccessibleInterface *accessible = accessibleInterface(); accessibleDebugClientCalls(accessible); - if (!accessible->isValid()) + if (!accessible) return E_FAIL; *name = 0; if (QAccessibleActionInterface *actionIface = actionInterface()) { @@ -619,8 +635,9 @@ HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_name(long actionIndex, BSTR HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_localizedName(long actionIndex, BSTR *localizedName) { + QAccessibleInterface *accessible = accessibleInterface(); accessibleDebugClientCalls(accessible); - if (!accessible->isValid()) + if (!accessible) return E_FAIL; *localizedName = 0; if (QAccessibleActionInterface *actionIface = actionInterface()) { @@ -639,8 +656,9 @@ HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_localizedName(long actionIn **************************************************************/ HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_locationInParent(long *x, long *y) { + QAccessibleInterface *accessible = accessibleInterface(); accessibleDebugClientCalls(accessible); - if (!accessible->isValid()) + if (!accessible) return E_FAIL; QPoint topLeft = accessible->rect().topLeft(); @@ -656,8 +674,9 @@ HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_locationInParent(long *x, l HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_foreground(IA2Color *foreground) { + QAccessibleInterface *accessible = accessibleInterface(); accessibleDebugClientCalls(accessible); - if (!accessible->isValid()) + if (!accessible) return E_FAIL; // IA2Color is a typedef for long @@ -667,8 +686,9 @@ HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_foreground(IA2Color *foregr HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_background(IA2Color *background) { + QAccessibleInterface *accessible = accessibleInterface(); accessibleDebugClientCalls(accessible); - if (!accessible->isValid()) + if (!accessible) return E_FAIL; // IA2Color is a typedef for long @@ -687,6 +707,8 @@ HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_background(IA2Color *backgr */ QString QWindowsIA2Accessible::textForRange(int startOffset, int endOffset) const { + QAccessibleInterface *accessible = accessibleInterface(); + if (QAccessibleTextInterface *textIface = accessible->textInterface()) { if (endOffset == IA2_TEXT_OFFSET_LENGTH) endOffset = textIface->characterCount(); @@ -704,6 +726,7 @@ QString QWindowsIA2Accessible::textForRange(int startOffset, int endOffset) cons */ void QWindowsIA2Accessible::replaceTextFallback(long startOffset, long endOffset, const QString &txt) { + QAccessibleInterface *accessible = accessibleInterface(); QString t = textForRange(0, -1); if (endOffset == IA2_TEXT_OFFSET_LENGTH) endOffset = t.length(); @@ -717,6 +740,7 @@ void QWindowsIA2Accessible::replaceTextFallback(long startOffset, long endOffset HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::copyText(long startOffset, long endOffset) { + QAccessibleInterface *accessible = accessibleInterface(); accessibleDebugClientCalls(accessible); #ifndef QT_NO_CLIPBOARD const QString t = textForRange(startOffset, endOffset); @@ -729,6 +753,7 @@ HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::copyText(long startOffset, long HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::deleteText(long startOffset, long endOffset) { + QAccessibleInterface *accessible = accessibleInterface(); accessibleDebugClientCalls(accessible); if (QAccessibleEditableTextInterface *editableTextIface = accessible->editableTextInterface()) editableTextIface->deleteText(startOffset, endOffset); @@ -739,6 +764,7 @@ HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::deleteText(long startOffset, lo HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::insertText(long offset, BSTR *text) { + QAccessibleInterface *accessible = accessibleInterface(); accessibleDebugClientCalls(accessible); const QString txt(BSTRToQString(*text)); if (QAccessibleEditableTextInterface *editableTextIface = accessible->editableTextInterface()) @@ -750,6 +776,7 @@ HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::insertText(long offset, BSTR *t HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::cutText(long startOffset, long endOffset) { + QAccessibleInterface *accessible = accessibleInterface(); accessibleDebugClientCalls(accessible); #ifndef QT_NO_CLIPBOARD const QString t = textForRange(startOffset, endOffset); @@ -766,6 +793,7 @@ HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::cutText(long startOffset, long HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::pasteText(long offset) { + QAccessibleInterface *accessible = accessibleInterface(); accessibleDebugClientCalls(accessible); #ifndef QT_NO_CLIPBOARD const QString txt = QGuiApplication::clipboard()->text(); @@ -781,6 +809,7 @@ HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::pasteText(long offset) HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::replaceText(long startOffset, long endOffset, BSTR *text) { + QAccessibleInterface *accessible = accessibleInterface(); accessibleDebugClientCalls(accessible); const QString txt(BSTRToQString(*text)); if (QAccessibleEditableTextInterface *editableTextIface = accessible->editableTextInterface()) @@ -801,8 +830,9 @@ HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::setAttributes(long /*startOffse **************************************************************/ HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_cellAt( long row, long column, IUnknown **cell) { + QAccessibleInterface *accessible = accessibleInterface(); accessibleDebugClientCalls(accessible); - if (!accessible->isValid()) + if (!accessible) return E_FAIL; *cell = 0; @@ -817,8 +847,9 @@ HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_cellAt( long row, long colu HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_caption( IUnknown **captionInterface) { + QAccessibleInterface *accessible = accessibleInterface(); accessibleDebugClientCalls(accessible); - if (!accessible->isValid()) + if (!accessible) return E_FAIL; *captionInterface = 0; @@ -831,8 +862,9 @@ HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_caption( IUnknown **caption HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_columnDescription( long column, BSTR *description) { + QAccessibleInterface *accessible = accessibleInterface(); accessibleDebugClientCalls(accessible); - if (!accessible->isValid()) + if (!accessible) return E_FAIL; *description = 0; @@ -846,8 +878,9 @@ HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_columnDescription( long col HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_nColumns( long *columnCount) { + QAccessibleInterface *accessible = accessibleInterface(); accessibleDebugClientCalls(accessible); - if (!accessible->isValid()) + if (!accessible) return E_FAIL; if (QAccessibleTableInterface *tableIface = tableInterface()) { @@ -859,8 +892,9 @@ HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_nColumns( long *columnCount HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_nRows(long *rowCount) { + QAccessibleInterface *accessible = accessibleInterface(); accessibleDebugClientCalls(accessible); - if (!accessible->isValid()) + if (!accessible) return E_FAIL; if (QAccessibleTableInterface *tableIface = tableInterface()) { @@ -872,8 +906,9 @@ HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_nRows(long *rowCount) HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_nSelectedCells(long *cellCount) { + QAccessibleInterface *accessible = accessibleInterface(); accessibleDebugClientCalls(accessible); - if (!accessible->isValid()) + if (!accessible) return E_FAIL; if (QAccessibleTableInterface *tableIface = tableInterface()) { @@ -885,8 +920,9 @@ HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_nSelectedCells(long *cellCo HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_nSelectedColumns(long *columnCount) { + QAccessibleInterface *accessible = accessibleInterface(); accessibleDebugClientCalls(accessible); - if (!accessible->isValid()) + if (!accessible) return E_FAIL; if (QAccessibleTableInterface *tableIface = tableInterface()) { @@ -898,8 +934,9 @@ HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_nSelectedColumns(long *colu HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_nSelectedRows(long *rowCount) { + QAccessibleInterface *accessible = accessibleInterface(); accessibleDebugClientCalls(accessible); - if (!accessible->isValid()) + if (!accessible) return E_FAIL; if (QAccessibleTableInterface *tableIface = tableInterface()) { @@ -911,8 +948,9 @@ HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_nSelectedRows(long *rowCoun HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_rowDescription(long row, BSTR *description) { + QAccessibleInterface *accessible = accessibleInterface(); accessibleDebugClientCalls(accessible); - if (!accessible->isValid()) + if (!accessible) return E_FAIL; *description = 0; @@ -926,10 +964,11 @@ HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_rowDescription(long row, BS HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_selectedCells(IUnknown ***cells, long *nSelectedCells) { + QAccessibleInterface *accessible = accessibleInterface(); accessibleDebugClientCalls(accessible); Q_UNUSED(cells); Q_UNUSED(nSelectedCells); - if (!accessible->isValid()) + if (!accessible) return E_FAIL; QList<QAccessibleInterface*> selectedCells = tableInterface()->selectedCells(); @@ -938,8 +977,9 @@ HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_selectedCells(IUnknown ***c HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_selectedColumns(long **selectedColumns, long *nColumns) { + QAccessibleInterface *accessible = accessibleInterface(); accessibleDebugClientCalls(accessible); - if (!accessible->isValid()) + if (!accessible) return E_FAIL; if (QAccessibleTableInterface *tableIface = tableInterface()) { @@ -958,8 +998,9 @@ HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_selectedColumns(long **sele HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_selectedRows(long **selectedRows, long *nRows) { + QAccessibleInterface *accessible = accessibleInterface(); accessibleDebugClientCalls(accessible); - if (!accessible->isValid()) + if (!accessible) return E_FAIL; if (QAccessibleTableInterface *tableIface = tableInterface()) { @@ -978,8 +1019,9 @@ HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_selectedRows(long **selecte HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_summary(IUnknown **summaryInterface) { + QAccessibleInterface *accessible = accessibleInterface(); accessibleDebugClientCalls(accessible); - if (!accessible->isValid()) + if (!accessible) return E_FAIL; *summaryInterface = 0; @@ -992,8 +1034,9 @@ HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_summary(IUnknown **summaryI HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_isColumnSelected(long column, boolean *isSelected) { + QAccessibleInterface *accessible = accessibleInterface(); accessibleDebugClientCalls(accessible); - if (!accessible->isValid()) + if (!accessible) return E_FAIL; if (QAccessibleTableInterface *tableIface = tableInterface()) { @@ -1005,8 +1048,9 @@ HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_isColumnSelected(long colum HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_isRowSelected(long row, boolean *isSelected) { + QAccessibleInterface *accessible = accessibleInterface(); accessibleDebugClientCalls(accessible); - if (!accessible->isValid()) + if (!accessible) return E_FAIL; if (QAccessibleTableInterface *tableIface = tableInterface()) { @@ -1018,8 +1062,9 @@ HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_isRowSelected(long row, boo HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::selectRow(long row) { + QAccessibleInterface *accessible = accessibleInterface(); accessibleDebugClientCalls(accessible); - if (!accessible->isValid()) + if (!accessible) return E_FAIL; if (QAccessibleTableInterface *tableIface = tableInterface()) { @@ -1031,8 +1076,9 @@ HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::selectRow(long row) HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::selectColumn(long column) { + QAccessibleInterface *accessible = accessibleInterface(); accessibleDebugClientCalls(accessible); - if (!accessible->isValid()) + if (!accessible) return E_FAIL; if (QAccessibleTableInterface *tableIface = tableInterface()) { @@ -1044,8 +1090,9 @@ HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::selectColumn(long column) HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::unselectRow(long row) { + QAccessibleInterface *accessible = accessibleInterface(); accessibleDebugClientCalls(accessible); - if (!accessible->isValid()) + if (!accessible) return E_FAIL; if (QAccessibleTableInterface *tableIface = tableInterface()) { @@ -1057,8 +1104,9 @@ HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::unselectRow(long row) HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::unselectColumn(long column) { + QAccessibleInterface *accessible = accessibleInterface(); accessibleDebugClientCalls(accessible); - if (!accessible->isValid()) + if (!accessible) return E_FAIL; if (QAccessibleTableInterface *tableIface = tableInterface()) { @@ -1070,8 +1118,9 @@ HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::unselectColumn(long column) HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_modelChange( IA2TableModelChange * /*modelChange*/) { + QAccessibleInterface *accessible = accessibleInterface(); accessibleDebugClientCalls(accessible); - if (!accessible->isValid()) + if (!accessible) return E_FAIL; return E_NOTIMPL; } @@ -1081,8 +1130,9 @@ HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_modelChange( IA2TableModelC \**************************************************************/ HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_columnExtent(long *nColumnsSpanned) { + QAccessibleInterface *accessible = accessibleInterface(); accessibleDebugClientCalls(accessible); - if (!accessible->isValid()) + if (!accessible) return E_FAIL; *nColumnsSpanned = tableCellInterface()->columnExtent(); @@ -1092,8 +1142,9 @@ HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_columnExtent(long *nColumns HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_columnHeaderCells(IUnknown ***cellAccessibles, long *nColumnHeaderCells) { + QAccessibleInterface *accessible = accessibleInterface(); accessibleDebugClientCalls(accessible); - if (!accessible->isValid()) + if (!accessible) return E_FAIL; const QList<QAccessibleInterface*> headerCells = tableCellInterface()->columnHeaderCells(); return wrapListOfCells(headerCells, cellAccessibles, nColumnHeaderCells); @@ -1101,8 +1152,9 @@ HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_columnHeaderCells(IUnknown HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_columnIndex(long *columnIndex) { + QAccessibleInterface *accessible = accessibleInterface(); accessibleDebugClientCalls(accessible); - if (!accessible->isValid()) + if (!accessible) return E_FAIL; *columnIndex = tableCellInterface()->columnIndex(); return S_OK; @@ -1110,8 +1162,9 @@ HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_columnIndex(long *columnInd HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_rowExtent(long *nRowsSpanned) { + QAccessibleInterface *accessible = accessibleInterface(); accessibleDebugClientCalls(accessible); - if (!accessible->isValid()) + if (!accessible) return E_FAIL; *nRowsSpanned = tableCellInterface()->rowExtent(); return S_OK; @@ -1120,8 +1173,9 @@ HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_rowExtent(long *nRowsSpanne HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_rowHeaderCells(IUnknown ***cellAccessibles, long *nRowHeaderCells) { + QAccessibleInterface *accessible = accessibleInterface(); accessibleDebugClientCalls(accessible); - if (!accessible->isValid()) + if (!accessible) return E_FAIL; const QList<QAccessibleInterface*> headerCells = tableCellInterface()->rowHeaderCells(); return wrapListOfCells(headerCells, cellAccessibles, nRowHeaderCells); @@ -1129,8 +1183,9 @@ HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_rowHeaderCells(IUnknown *** HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_rowIndex(long *rowIndex) { + QAccessibleInterface *accessible = accessibleInterface(); accessibleDebugClientCalls(accessible); - if (!accessible->isValid()) + if (!accessible) return E_FAIL; *rowIndex = tableCellInterface()->rowIndex(); return S_OK; @@ -1138,8 +1193,9 @@ HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_rowIndex(long *rowIndex) HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_isSelected( boolean *isSelected) { + QAccessibleInterface *accessible = accessibleInterface(); accessibleDebugClientCalls(accessible); - if (!accessible->isValid()) + if (!accessible) return E_FAIL; *isSelected = tableCellInterface()->isSelected(); return S_OK; @@ -1149,8 +1205,9 @@ HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_rowColumnExtents(long *row, long *rowExtents, long *columnExtents, boolean *isSelected) { + QAccessibleInterface *accessible = accessibleInterface(); accessibleDebugClientCalls(accessible); - if (!accessible->isValid()) + if (!accessible) return E_FAIL; tableCellInterface()->rowColumnExtents((int*)row, (int*)column, (int*)rowExtents, (int*)columnExtents, (bool*)isSelected); @@ -1159,8 +1216,9 @@ HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_rowColumnExtents(long *row, HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_table(IUnknown **table) { + QAccessibleInterface *accessible = accessibleInterface(); accessibleDebugClientCalls(accessible); - if (!accessible->isValid()) + if (!accessible) return E_FAIL; QAccessibleInterface *tableIface = tableCellInterface()->table(); @@ -1175,6 +1233,7 @@ HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_table(IUnknown **table) HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::addSelection(long startOffset, long endOffset) { + QAccessibleInterface *accessible = accessibleInterface(); accessibleDebugClientCalls(accessible); if (QAccessibleTextInterface *text = textInterface()) { text->addSelection(startOffset, endOffset); @@ -1188,6 +1247,7 @@ HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_attributes(long offset, long *endOffset, BSTR *textAttributes) { + QAccessibleInterface *accessible = accessibleInterface(); accessibleDebugClientCalls(accessible); if (QAccessibleTextInterface *text = textInterface()) { const QString attrs = text->attributes(offset, (int*)startOffset, (int*)endOffset); @@ -1199,6 +1259,7 @@ HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_attributes(long offset, HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_caretOffset(long *offset) { + QAccessibleInterface *accessible = accessibleInterface(); accessibleDebugClientCalls(accessible); if (QAccessibleTextInterface *text = textInterface()) { *offset = text->cursorPosition(); @@ -1215,6 +1276,7 @@ HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_characterExtents(long offse long *width, long *height) { + QAccessibleInterface *accessible = accessibleInterface(); accessibleDebugClientCalls(accessible); if (QAccessibleTextInterface *text = textInterface()) { QRect rect = text->characterRect(offset); @@ -1228,6 +1290,7 @@ HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_characterExtents(long offse HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_nSelections(long *nSelections) { + QAccessibleInterface *accessible = accessibleInterface(); accessibleDebugClientCalls(accessible); if (QAccessibleTextInterface *text = textInterface()) { *nSelections = text->selectionCount(); @@ -1241,6 +1304,7 @@ HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_offsetAtPoint(long x, enum IA2CoordinateType coordType, long *offset) { + QAccessibleInterface *accessible = accessibleInterface(); accessibleDebugClientCalls(accessible); if (QAccessibleTextInterface *text = textInterface()) { QPoint screenPos = mapToScreenPos(coordType, x, y); @@ -1255,6 +1319,7 @@ HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_selection(long selectionInd long *startOffset, long *endOffset) { + QAccessibleInterface *accessible = accessibleInterface(); accessibleDebugClientCalls(accessible); if (QAccessibleTextInterface *text = textInterface()) { text->selection(selectionIndex, (int*)startOffset, (int*)endOffset); @@ -1267,6 +1332,7 @@ HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_text(long startOffset, long endOffset, BSTR *text) { + QAccessibleInterface *accessible = accessibleInterface(); accessibleDebugClientCalls(accessible); if (QAccessibleTextInterface *textif = textInterface()) { const QString t = textif->text(startOffset, endOffset); @@ -1285,6 +1351,7 @@ HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_textBeforeOffset(long offse long *endOffset, BSTR *text) { + QAccessibleInterface *accessible = accessibleInterface(); accessibleDebugClientCalls(accessible); if (QAccessibleTextInterface *textIface = textInterface()) { const QString txt = textIface->textBeforeOffset(offset, (QAccessible2::BoundaryType)boundaryType, (int*)startOffset, (int*)endOffset); @@ -1304,6 +1371,7 @@ HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_textAfterOffset( long *endOffset, BSTR *text) { + QAccessibleInterface *accessible = accessibleInterface(); accessibleDebugClientCalls(accessible); if (QAccessibleTextInterface *textIface = textInterface()) { const QString txt = textIface->textAfterOffset(offset, (QAccessible2::BoundaryType)boundaryType, (int*)startOffset, (int*)endOffset); @@ -1322,6 +1390,7 @@ HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_textAtOffset(long offset, long *endOffset, BSTR *text) { + QAccessibleInterface *accessible = accessibleInterface(); accessibleDebugClientCalls(accessible); if (QAccessibleTextInterface *textIface = textInterface()) { const QString txt = textIface->textAtOffset(offset, (QAccessible2::BoundaryType)boundaryType, (int*)startOffset, (int*)endOffset); @@ -1336,6 +1405,7 @@ HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_textAtOffset(long offset, HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::removeSelection(long selectionIndex) { + QAccessibleInterface *accessible = accessibleInterface(); accessibleDebugClientCalls(accessible); if (QAccessibleTextInterface *textIface = textInterface()) { textIface->removeSelection(selectionIndex); @@ -1346,6 +1416,7 @@ HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::removeSelection(long selectionI HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::setCaretOffset(long offset) { + QAccessibleInterface *accessible = accessibleInterface(); accessibleDebugClientCalls(accessible); if (QAccessibleTextInterface *textIface = textInterface()) { textIface->setCursorPosition(offset); @@ -1358,6 +1429,7 @@ HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::setSelection(long selectionInde long startOffset, long endOffset) { + QAccessibleInterface *accessible = accessibleInterface(); accessibleDebugClientCalls(accessible); if (QAccessibleTextInterface *textIface = textInterface()) { textIface->setSelection(selectionIndex, startOffset, endOffset); @@ -1368,6 +1440,7 @@ HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::setSelection(long selectionInde HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_nCharacters(long *nCharacters) { + QAccessibleInterface *accessible = accessibleInterface(); accessibleDebugClientCalls(accessible); if (QAccessibleTextInterface *textIface = textInterface()) { *nCharacters = textIface->characterCount(); @@ -1380,6 +1453,7 @@ HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::scrollSubstringTo(long startInd long endIndex, enum IA2ScrollType scrollType) { + QAccessibleInterface *accessible = accessibleInterface(); accessibleDebugClientCalls(accessible); if (QAccessibleTextInterface *textIface = textInterface()) { Q_UNUSED(scrollType); //### @@ -1421,8 +1495,9 @@ HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_oldText(IA2TextSegment *old **************************************************************/ HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_currentValue(VARIANT *currentValue) { + QAccessibleInterface *accessible = accessibleInterface(); accessibleDebugClientCalls(accessible); - if (!accessible->isValid()) + if (!accessible) return E_FAIL; if (QAccessibleValueInterface *valueIface = valueInterface()) { const QVariant var = valueIface->currentValue(); @@ -1436,8 +1511,9 @@ HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_currentValue(VARIANT *curre HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::setCurrentValue(VARIANT value) { + QAccessibleInterface *accessible = accessibleInterface(); accessibleDebugClientCalls(accessible); - if (!accessible->isValid()) + if (!accessible) return E_FAIL; HRESULT hr = S_FALSE; if (QAccessibleValueInterface *valueIface = valueInterface()) { @@ -1452,8 +1528,9 @@ HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::setCurrentValue(VARIANT value) HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_maximumValue(VARIANT *maximumValue) { + QAccessibleInterface *accessible = accessibleInterface(); accessibleDebugClientCalls(accessible); - if (!accessible->isValid()) + if (!accessible) return E_FAIL; if (QAccessibleValueInterface *valueIface = valueInterface()) { const QVariant var = valueIface->maximumValue(); @@ -1466,8 +1543,9 @@ HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_maximumValue(VARIANT *maxim HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_minimumValue(VARIANT *minimumValue) { + QAccessibleInterface *accessible = accessibleInterface(); accessibleDebugClientCalls(accessible); - if (!accessible->isValid()) + if (!accessible) return E_FAIL; if (QAccessibleValueInterface *valueIface = valueInterface()) { const QVariant var = valueIface->minimumValue(); @@ -1539,6 +1617,7 @@ HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::QueryService(REFGUID guidServic */ HRESULT QWindowsIA2Accessible::getRelationsHelper(IAccessibleRelation **relations, int startIndex, long maxRelations, long *nRelations /* = 0*/) { + QAccessibleInterface *accessible = accessibleInterface(); if (nRelations) *nRelations = 0; typedef QPair<QAccessibleInterface *, QAccessible::Relation> RelationEntry; @@ -1588,37 +1667,6 @@ HRESULT QWindowsIA2Accessible::wrapListOfCells(const QList<QAccessibleInterface* return count > 0 ? S_OK : S_FALSE; } -uint QWindowsIA2Accessible::uniqueID() const -{ - uint uid = 0; - if (QObject *obj = accessible->object()) - uid = qHash(obj); - - if (!uid) { - QAccessibleInterface *acc = accessible; - QVector<int> indexOfNodes; - while (acc && acc->isValid() && !acc->object()) { - QAccessibleInterface *par = acc->parent(); - indexOfNodes.append(par->indexOfChild(acc)); - if (acc != accessible) - delete acc; - acc = par; - } - if (acc) { - if (acc->object()) { - uid = qHash(acc->object()); - for (int i = 0; i < indexOfNodes.count(); ++i) - uid = qHash(uid + indexOfNodes.at(i)); - - } - if (acc != accessible) - delete acc; - } - } - return uid; -} - - #define IF_EQUAL_RETURN_IIDSTRING(id, iid) if (id == iid) return QByteArray(#iid) QByteArray QWindowsIA2Accessible::IIDToString(REFIID id) diff --git a/src/plugins/platforms/windows/accessible/iaccessible2.h b/src/plugins/platforms/windows/accessible/iaccessible2.h index af9698b9b2..a391d495f9 100644 --- a/src/plugins/platforms/windows/accessible/iaccessible2.h +++ b/src/plugins/platforms/windows/accessible/iaccessible2.h @@ -132,7 +132,7 @@ public: /* IAccessibleTable2 */ HRESULT STDMETHODCALLTYPE get_cellAt( long row, long column, IUnknown **cell); - HRESULT STDMETHODCALLTYPE get_caption( IUnknown **accessible); + HRESULT STDMETHODCALLTYPE get_caption( IUnknown **accessibleInterface); HRESULT STDMETHODCALLTYPE get_columnDescription( long column, BSTR *description); HRESULT STDMETHODCALLTYPE get_nColumns( long *columnCount); HRESULT STDMETHODCALLTYPE get_nRows( long *rowCount); @@ -143,7 +143,7 @@ public: HRESULT STDMETHODCALLTYPE get_selectedCells( IUnknown ***cells, long *nSelectedCells); HRESULT STDMETHODCALLTYPE get_selectedColumns( long **selectedColumns, long *nColumns); HRESULT STDMETHODCALLTYPE get_selectedRows( long **selectedRows, long *nRows); - HRESULT STDMETHODCALLTYPE get_summary( IUnknown **accessible); + HRESULT STDMETHODCALLTYPE get_summary( IUnknown **accessibleInterface); HRESULT STDMETHODCALLTYPE get_isColumnSelected( long column, boolean *isSelected); HRESULT STDMETHODCALLTYPE get_isRowSelected( long row, boolean *isSelected); HRESULT STDMETHODCALLTYPE selectRow( long row); @@ -206,22 +206,27 @@ public: /* private helper functions */ private: inline QAccessibleTextInterface *textInterface() const { - return accessible->isValid() ? accessible->textInterface() : static_cast<QAccessibleTextInterface *>(0); + QAccessibleInterface *accessible = accessibleInterface(); + return accessible ? accessible->textInterface() : static_cast<QAccessibleTextInterface *>(0); } inline QAccessibleActionInterface *actionInterface() const { + QAccessibleInterface *accessible = accessibleInterface(); return accessible->actionInterface(); } inline QAccessibleValueInterface *valueInterface() const { + QAccessibleInterface *accessible = accessibleInterface(); return accessible->valueInterface(); } inline QAccessibleTableInterface *tableInterface() const { + QAccessibleInterface *accessible = accessibleInterface(); return accessible->tableInterface(); } inline QAccessibleTableCellInterface *tableCellInterface() const { + QAccessibleInterface *accessible = accessibleInterface(); return accessible->tableCellInterface(); } @@ -231,6 +236,7 @@ private: \a x and \y (out) is in parent relative position if coordType == IA2_COORDTYPE_PARENT_RELATIVE */ void mapFromScreenPos(enum IA2CoordinateType coordType, const QPoint &screenPos, long *x, long *y) const { + QAccessibleInterface *accessible = accessibleInterface(); if (coordType == IA2_COORDTYPE_PARENT_RELATIVE) { // caller wants relative to parent if (QAccessibleInterface *parent = accessible->parent()) { @@ -250,6 +256,7 @@ private: \return a screen relative position */ QPoint mapToScreenPos(enum IA2CoordinateType coordType, long x, long y) const { + QAccessibleInterface *accessible = accessibleInterface(); if (coordType == IA2_COORDTYPE_PARENT_RELATIVE) { if (QAccessibleInterface *parent = accessible->parent()) { const QRect parentScreenRect = parent->rect(); @@ -261,7 +268,6 @@ private: HRESULT getRelationsHelper(IAccessibleRelation **relations, int startIndex, long maxRelations, long *nRelations = 0); HRESULT wrapListOfCells(const QList<QAccessibleInterface*> &inputCells, IUnknown ***outputAccessibles, long *nCellCount); - uint uniqueID() const; QByteArray IIDToString(REFIID id); QString textForRange(int startOffset, int endOffset) const; void replaceTextFallback(long startOffset, long endOffset, const QString &txt); diff --git a/src/plugins/platforms/windows/accessible/qwindowsaccessibility.cpp b/src/plugins/platforms/windows/accessible/qwindowsaccessibility.cpp index 79d0934ebb..f222deeeac 100644 --- a/src/plugins/platforms/windows/accessible/qwindowsaccessibility.cpp +++ b/src/plugins/platforms/windows/accessible/qwindowsaccessibility.cpp @@ -86,14 +86,8 @@ #include "../qtwindows_additional.h" - -// This stuff is used for widgets/items with no window handle: -typedef QMap<int, QPair<QPointer<QObject>,int> > NotifyMap; -Q_GLOBAL_STATIC(NotifyMap, qAccessibleRecentSentEvents) - QT_BEGIN_NAMESPACE - /*! \!internal \class QWindowsAccessibility @@ -172,7 +166,6 @@ void QWindowsAccessibility::notifyAccessibilityUpdate(QAccessibleEvent *event) if (!iface) // ### This should not happen, maybe make it an assert. return; QWindow *window = QWindowsAccessibility::windowHelper(iface); - delete iface; if (!window) { window = QGuiApplication::focusWindow(); @@ -185,27 +178,9 @@ void QWindowsAccessibility::notifyAccessibilityUpdate(QAccessibleEvent *event) return; HWND hWnd = (HWND)platform->nativeResourceForWindow("handle", window); - static int eventNum = 0; if (event->type() != QAccessible::MenuCommand && // MenuCommand is faked event->type() != QAccessible::ObjectDestroyed) { - /* In some rare occasions, the server (Qt) might get a ::get_accChild call with a - childId that references an entry in the cache where there was a dangling - QObject-pointer. Previously we crashed on this. - - There is no point in actually notifying the AT client that the object got destroyed, - because the AT client won't query for get_accChild if the event is ObjectDestroyed - anyway, and we have no other way of mapping the eventId argument to the actual - child/descendant object. (Firefox seems to simply completely ignore - EVENT_OBJECT_DESTROY). - - We therefore guard each QObject in the cache with a QPointer, and only notify the AT - client if the type is not ObjectDestroyed. - */ - eventNum %= 50; //[0..49] - int eventId = - (eventNum - 1); - qAccessibleRecentSentEvents()->insert(eventId, qMakePair(QPointer<QObject>(event->object()), event->child())); - ::NotifyWinEvent(event->type(), hWnd, OBJID_CLIENT, eventId); - ++eventNum; + ::NotifyWinEvent(event->type(), hWnd, OBJID_CLIENT, QAccessible::uniqueId(iface)); } #endif // Q_OS_WINCE } @@ -218,7 +193,6 @@ QWindow *QWindowsAccessibility::windowHelper(const QAccessibleInterface *iface) while (acc && acc->isValid() && !window) { window = acc->window(); QAccessibleInterface *par = acc->parent(); - delete acc; acc = par; } } @@ -233,6 +207,11 @@ IAccessible *QWindowsAccessibility::wrap(QAccessibleInterface *acc) { if (!acc) return 0; + + // ### FIXME: maybe we should accept double insertions into the cache + if (!QAccessible::uniqueId(acc)) + QAccessible::registerAccessibleInterface(acc); + #ifdef Q_CC_MINGW QWindowsMsaaAccessible *wacc = new QWindowsMsaaAccessible(acc); #else @@ -243,15 +222,6 @@ IAccessible *QWindowsAccessibility::wrap(QAccessibleInterface *acc) return iacc; } -/*! - \internal -*/ -QPair<QObject*, int> QWindowsAccessibility::getCachedObject(int entryId) -{ - QPair<QPointer<QObject>, int> pair = qAccessibleRecentSentEvents()->value(entryId); - return qMakePair(pair.first.data(), pair.second); -} - /* void QWindowsAccessibility::setRootObject(QObject *o) { @@ -304,8 +274,6 @@ bool QWindowsAccessibility::handleAccessibleObjectFromWindowRequest(HWND hwnd, W iface->Release(); // the client will release the object again, and then it will destroy itself } return true; - } else { - delete acc; } } } diff --git a/src/plugins/platforms/windows/accessible/qwindowsaccessibility.h b/src/plugins/platforms/windows/accessible/qwindowsaccessibility.h index 5a6dc0c2e5..f25e2281a0 100644 --- a/src/plugins/platforms/windows/accessible/qwindowsaccessibility.h +++ b/src/plugins/platforms/windows/accessible/qwindowsaccessibility.h @@ -63,8 +63,6 @@ public: */ static IAccessible *wrap(QAccessibleInterface *acc); static QWindow *windowHelper(const QAccessibleInterface *iface); - - static QPair<QObject*, int> getCachedObject(int entryId); }; QT_END_NAMESPACE diff --git a/src/plugins/platforms/windows/accessible/qwindowsmsaaaccessible.cpp b/src/plugins/platforms/windows/accessible/qwindowsmsaaaccessible.cpp index 9958615d45..7eb1bd30c0 100644 --- a/src/plugins/platforms/windows/accessible/qwindowsmsaaaccessible.cpp +++ b/src/plugins/platforms/windows/accessible/qwindowsmsaaaccessible.cpp @@ -186,21 +186,6 @@ HRESULT STDMETHODCALLTYPE QWindowsEnumerate::Skip(unsigned long celt) return S_OK; } -static bool compareAccessible(QAccessibleInterface *one, QAccessibleInterface *other) -{ - if (one == other) return true; - if (!one || !other) return false; - - if (one->object() && other->object() && (one->object() == other->object())) - return true; - QAIPointer onePar(one->parent()); - QAIPointer otherPar(other->parent()); - - if (compareAccessible(onePar.data(), otherPar.data())) - return onePar->indexOfChild(one) == otherPar->indexOfChild(other); - return false; -} - #ifndef QT_NO_DEBUG bool debug_accessibility() { @@ -232,7 +217,9 @@ HRESULT STDMETHODCALLTYPE QWindowsMsaaAccessible::QueryInterface(REFIID id, LPVO QByteArray strIID = IIDToString(id); if (!strIID.isEmpty()) { - QString ss; QDebug dbg(&ss); dbg << accessible; + QString ss; + QDebug dbg(&ss); + dbg << accessibleInterface(); accessibleDebug("QWindowsIA2Accessible::QI() - IID:%s, iface:%s ", strIID.constData(), qPrintable(ss)); } if (id == IID_IUnknown) { @@ -533,8 +520,9 @@ IAccessible::accHitTest documents the value returned in pvarID like this: */ HRESULT STDMETHODCALLTYPE QWindowsMsaaAccessible::accHitTest(long xLeft, long yTop, VARIANT *pvarID) { + QAccessibleInterface *accessible = accessibleInterface(); accessibleDebugClientCalls(accessible); - if (!accessible->isValid()) + if (!accessible) return E_FAIL; QAccessibleInterface *child = accessible->childAt(xLeft, yTop); @@ -571,14 +559,15 @@ HRESULT STDMETHODCALLTYPE QWindowsMsaaAccessible::accHitTest(long xLeft, long yT // moz: [important] HRESULT STDMETHODCALLTYPE QWindowsMsaaAccessible::accLocation(long *pxLeft, long *pyTop, long *pcxWidth, long *pcyHeight, VARIANT varID) { + QAccessibleInterface *accessible = accessibleInterface(); accessibleDebugClientCalls(accessible); - if (!accessible->isValid()) + if (!accessible) return E_FAIL; QRect rect; if (varID.lVal) { - QAIPointer child(childPointer(varID)); - if (!child) + QAccessibleInterface *child = accessible->child(varID.lVal - 1); + if (!child || !child->isValid()) return E_FAIL; rect = child->rect(); } else { @@ -596,8 +585,9 @@ HRESULT STDMETHODCALLTYPE QWindowsMsaaAccessible::accLocation(long *pxLeft, long // moz: [important, but no need to implement up/down/left/right] HRESULT STDMETHODCALLTYPE QWindowsMsaaAccessible::accNavigate(long navDir, VARIANT varStart, VARIANT *pvarEnd) { + QAccessibleInterface *accessible = accessibleInterface(); accessibleDebugClientCalls(accessible); - if (!accessible->isValid()) + if (!accessible) return E_FAIL; QAccessibleInterface *acc = 0; @@ -617,7 +607,6 @@ HRESULT STDMETHODCALLTYPE QWindowsMsaaAccessible::accNavigate(long navDir, VARIA index += (navDir == NAVDIR_NEXT) ? 1 : -1; if (index >= 0 && index < parent->childCount()) acc = parent->child(index); - delete parent; } } else { int index = varStart.lVal; @@ -646,7 +635,6 @@ HRESULT STDMETHODCALLTYPE QWindowsMsaaAccessible::accNavigate(long navDir, VARIA Q_ASSERT(sibling); if (i == indexOfOurself || sibling->state().invisible) { //ignore ourself and invisible siblings - delete sibling; continue; } @@ -660,7 +648,6 @@ HRESULT STDMETHODCALLTYPE QWindowsMsaaAccessible::accNavigate(long navDir, VARIA startp = QPoint(startg.left(), startg.top() + startg.height() / 2); sibp = QPoint(sibg.right(), sibg.top() + sibg.height() / 2); if (QPoint(sibc - startc).x() >= 0) { - delete sibling; continue; } distp = sibp - startp; @@ -669,7 +656,6 @@ HRESULT STDMETHODCALLTYPE QWindowsMsaaAccessible::accNavigate(long navDir, VARIA startp = QPoint(startg.right(), startg.top() + startg.height() / 2); sibp = QPoint(sibg.left(), sibg.top() + sibg.height() / 2); if (QPoint(sibc - startc).x() <= 0) { - delete sibling; continue; } distp = sibp - startp; @@ -678,7 +664,6 @@ HRESULT STDMETHODCALLTYPE QWindowsMsaaAccessible::accNavigate(long navDir, VARIA startp = QPoint(startg.left() + startg.width() / 2, startg.top()); sibp = QPoint(sibg.left() + sibg.width() / 2, sibg.bottom()); if (QPoint(sibc - startc).y() >= 0) { - delete sibling; continue; } distp = sibp - startp; @@ -687,7 +672,6 @@ HRESULT STDMETHODCALLTYPE QWindowsMsaaAccessible::accNavigate(long navDir, VARIA startp = QPoint(startg.left() + startg.width() / 2, startg.bottom()); sibp = QPoint(sibg.left() + sibg.width() / 2, sibg.top()); if (QPoint(sibc - startc).y() <= 0) { - delete sibling; continue; } distp = sibp - startp; @@ -700,14 +684,10 @@ HRESULT STDMETHODCALLTYPE QWindowsMsaaAccessible::accNavigate(long navDir, VARIA // squared distance, (thus, no need to take the sqrt()). unsigned dist = distp.x() * distp.x() + distp.y() * distp.y(); if (dist < mindist) { - delete candidate; candidate = sibling; mindist = dist; - } else { - delete sibling; } } - delete pIface; acc = candidate; } } @@ -724,9 +704,6 @@ HRESULT STDMETHODCALLTYPE QWindowsMsaaAccessible::accNavigate(long navDir, VARIA (*pvarEnd).vt = VT_DISPATCH; (*pvarEnd).pdispVal = iface; return S_OK; - } else { - if (acc != accessible) - delete acc; } (*pvarEnd).vt = VT_EMPTY; @@ -736,8 +713,9 @@ HRESULT STDMETHODCALLTYPE QWindowsMsaaAccessible::accNavigate(long navDir, VARIA // moz: [important] HRESULT STDMETHODCALLTYPE QWindowsMsaaAccessible::get_accChild(VARIANT varChildID, IDispatch** ppdispChild) { + QAccessibleInterface *accessible = accessibleInterface(); accessibleDebugClientCalls(accessible); - if (!accessible->isValid()) + if (!accessible) return E_FAIL; if (varChildID.vt != VT_I4) @@ -745,38 +723,18 @@ HRESULT STDMETHODCALLTYPE QWindowsMsaaAccessible::get_accChild(VARIANT varChildI int childIndex = varChildID.lVal; + QAccessibleInterface *acc = 0; - if (childIndex < 0) { - const int entry = childIndex; - QPair<QObject*, int> ref = QWindowsAccessibility::getCachedObject(entry); - if (ref.first) { - acc = QAccessible::queryAccessibleInterface(ref.first); - if (acc && ref.second >= 0) { - QAccessibleInterface *res = acc->child(ref.second); - delete acc; - if (!res) - return E_INVALIDARG; - acc = res; - } - } else { - qWarning("get_accChild got a negative varChildID (%d), but did not find it in cache", childIndex); - } + + if (childIndex == 0) { + // Yes, some AT clients (Active Accessibility Object Inspector) + // actually ask for the same object. As a consequence, we need to clone ourselves: + acc = accessible; + } else if (childIndex < 0) { + acc = QAccessible::accessibleInterface((QAccessible::Id)childIndex); } else { - if (childIndex) { - acc = accessible->child(childIndex - 1); - } else { - // Yes, some AT clients (Active Accessibility Object Inspector) - // actually ask for the same object. As a consequence, we need to clone ourselves: - if (QAccessibleInterface *par = accessible->parent()) { - const int indexOf = par->indexOfChild(accessible); - if (indexOf == -1) - qWarning() << "inconsistent hierarchy, parent:" << par << "child:" << accessible; - else - acc = par->child(indexOf); - delete par; - } - } + acc = accessible->child(childIndex - 1); } if (acc) { @@ -790,8 +748,9 @@ HRESULT STDMETHODCALLTYPE QWindowsMsaaAccessible::get_accChild(VARIANT varChildI // moz: [important] HRESULT STDMETHODCALLTYPE QWindowsMsaaAccessible::get_accChildCount(long* pcountChildren) { + QAccessibleInterface *accessible = accessibleInterface(); accessibleDebugClientCalls(accessible); - if (!accessible->isValid()) + if (!accessible) return E_FAIL; *pcountChildren = accessible->childCount(); @@ -801,8 +760,9 @@ HRESULT STDMETHODCALLTYPE QWindowsMsaaAccessible::get_accChildCount(long* pcount // moz: [important] HRESULT STDMETHODCALLTYPE QWindowsMsaaAccessible::get_accParent(IDispatch** ppdispParent) { + QAccessibleInterface *accessible = accessibleInterface(); accessibleDebugClientCalls(accessible); - if (!accessible->isValid()) + if (!accessible) return E_FAIL; QAccessibleInterface *acc = accessible->parent(); @@ -810,8 +770,6 @@ HRESULT STDMETHODCALLTYPE QWindowsMsaaAccessible::get_accParent(IDispatch** ppdi if (IAccessible *iface = QWindowsAccessibility::wrap(acc)) { *ppdispParent = iface; return S_OK; - } else { - delete acc; } } @@ -825,8 +783,9 @@ HRESULT STDMETHODCALLTYPE QWindowsMsaaAccessible::get_accParent(IDispatch** ppdi HRESULT STDMETHODCALLTYPE QWindowsMsaaAccessible::accDoDefaultAction(VARIANT varID) { Q_UNUSED(varID); + QAccessibleInterface *accessible = accessibleInterface(); accessibleDebugClientCalls(accessible); - if (!accessible->isValid()) + if (!accessible) return E_FAIL; if (QAccessibleActionInterface *actionIface = accessible->actionInterface()) { @@ -842,8 +801,9 @@ HRESULT STDMETHODCALLTYPE QWindowsMsaaAccessible::accDoDefaultAction(VARIANT var HRESULT STDMETHODCALLTYPE QWindowsMsaaAccessible::get_accDefaultAction(VARIANT varID, BSTR* pszDefaultAction) { Q_UNUSED(varID); + QAccessibleInterface *accessible = accessibleInterface(); accessibleDebugClientCalls(accessible); - if (!accessible->isValid()) + if (!accessible) return E_FAIL; *pszDefaultAction = 0; @@ -857,14 +817,15 @@ HRESULT STDMETHODCALLTYPE QWindowsMsaaAccessible::get_accDefaultAction(VARIANT v HRESULT STDMETHODCALLTYPE QWindowsMsaaAccessible::get_accDescription(VARIANT varID, BSTR* pszDescription) { + QAccessibleInterface *accessible = accessibleInterface(); accessibleDebugClientCalls(accessible); - if (!accessible->isValid()) + if (!accessible) return E_FAIL; QString descr; if (varID.lVal) { - QAIPointer child = childPointer(varID); + QAccessibleInterface *child = childPointer(varID); if (!child) return E_FAIL; descr = child->text(QAccessible::Description); @@ -882,13 +843,14 @@ HRESULT STDMETHODCALLTYPE QWindowsMsaaAccessible::get_accDescription(VARIANT var HRESULT STDMETHODCALLTYPE QWindowsMsaaAccessible::get_accHelp(VARIANT varID, BSTR *pszHelp) { + QAccessibleInterface *accessible = accessibleInterface(); accessibleDebugClientCalls(accessible); - if (!accessible->isValid()) + if (!accessible) return E_FAIL; QString help; if (varID.lVal) { - QAIPointer child = childPointer(varID); + QAccessibleInterface *child = childPointer(varID); if (!child) return E_FAIL; help = child->text(QAccessible::Help); @@ -912,8 +874,9 @@ HRESULT STDMETHODCALLTYPE QWindowsMsaaAccessible::get_accHelpTopic(BSTR *, VARIA HRESULT STDMETHODCALLTYPE QWindowsMsaaAccessible::get_accKeyboardShortcut(VARIANT varID, BSTR *pszKeyboardShortcut) { Q_UNUSED(varID); + QAccessibleInterface *accessible = accessibleInterface(); accessibleDebugClientCalls(accessible); - if (!accessible->isValid()) + if (!accessible) return E_FAIL; *pszKeyboardShortcut = 0; @@ -933,29 +896,26 @@ static QAccessibleInterface *relatedInterface(QAccessibleInterface *iface, QAcce typedef QPair<QAccessibleInterface *, QAccessible::Relation> RelationPair; QVector<RelationPair> rels = iface->relations(flag); - for (int i = 1; i < rels.count(); ++i) - delete rels.at(i).first; - return rels.value(0).first; } // moz: [important] HRESULT STDMETHODCALLTYPE QWindowsMsaaAccessible::get_accName(VARIANT varID, BSTR* pszName) { + QAccessibleInterface *accessible = accessibleInterface(); accessibleDebugClientCalls(accessible); - if (!accessible->isValid()) + if (!accessible) return E_FAIL; QString name; if (varID.lVal) { - QAIPointer child = childPointer(varID); + QAccessibleInterface *child = childPointer(varID); if (!child) return E_FAIL; name = child->text(QAccessible::Name); if (name.isEmpty()) { - if (QAccessibleInterface *labelInterface = relatedInterface(child.data(), QAccessible::Label)) { + if (QAccessibleInterface *labelInterface = relatedInterface(child, QAccessible::Label)) { name = labelInterface->text(QAccessible::Name); - delete labelInterface; } } } else { @@ -963,7 +923,6 @@ HRESULT STDMETHODCALLTYPE QWindowsMsaaAccessible::get_accName(VARIANT varID, BST if (name.isEmpty()) { if (QAccessibleInterface *labelInterface = relatedInterface(accessible, QAccessible::Label)) { name = labelInterface->text(QAccessible::Name); - delete labelInterface; } } } @@ -978,6 +937,7 @@ HRESULT STDMETHODCALLTYPE QWindowsMsaaAccessible::get_accName(VARIANT varID, BST HRESULT STDMETHODCALLTYPE QWindowsMsaaAccessible::put_accName(VARIANT, BSTR) { + QAccessibleInterface *accessible = accessibleInterface(); accessibleDebugClientCalls(accessible); return DISP_E_MEMBERNOTFOUND; } @@ -985,13 +945,14 @@ HRESULT STDMETHODCALLTYPE QWindowsMsaaAccessible::put_accName(VARIANT, BSTR) // moz: [important] HRESULT STDMETHODCALLTYPE QWindowsMsaaAccessible::get_accRole(VARIANT varID, VARIANT *pvarRole) { + QAccessibleInterface *accessible = accessibleInterface(); accessibleDebugClientCalls(accessible); - if (!accessible->isValid()) + if (!accessible) return E_FAIL; QAccessible::Role role; if (varID.lVal) { - QAIPointer child = childPointer(varID); + QAccessibleInterface *child = childPointer(varID); if (!child) return E_FAIL; role = child->role(); @@ -1019,14 +980,15 @@ HRESULT STDMETHODCALLTYPE QWindowsMsaaAccessible::get_accRole(VARIANT varID, VAR // moz: [important] HRESULT STDMETHODCALLTYPE QWindowsMsaaAccessible::get_accState(VARIANT varID, VARIANT *pvarState) { + QAccessibleInterface *accessible = accessibleInterface(); accessibleDebugClientCalls(accessible); - if (!accessible->isValid()) + if (!accessible) return E_FAIL; QAccessible::State state; if (varID.lVal) { - QAIPointer child = childPointer(varID); - if (!child.data()) + QAccessibleInterface *child = childPointer(varID); + if (!child) return E_FAIL; state = child->state(); } else { @@ -1095,11 +1057,12 @@ HRESULT STDMETHODCALLTYPE QWindowsMsaaAccessible::get_accState(VARIANT varID, VA // moz: [important] HRESULT STDMETHODCALLTYPE QWindowsMsaaAccessible::get_accValue(VARIANT varID, BSTR* pszValue) { + QAccessibleInterface *accessible = accessibleInterface(); accessibleDebugClientCalls(accessible); if (varID.vt != VT_I4) return E_INVALIDARG; - if (!accessible->isValid() || varID.lVal) { + if (!accessible || !accessible->isValid() || varID.lVal) { return E_FAIL; } @@ -1121,6 +1084,7 @@ HRESULT STDMETHODCALLTYPE QWindowsMsaaAccessible::get_accValue(VARIANT varID, BS HRESULT STDMETHODCALLTYPE QWindowsMsaaAccessible::put_accValue(VARIANT, BSTR) { + QAccessibleInterface *accessible = accessibleInterface(); accessibleDebugClientCalls(accessible); return DISP_E_MEMBERNOTFOUND; } @@ -1130,8 +1094,9 @@ HRESULT STDMETHODCALLTYPE QWindowsMsaaAccessible::accSelect(long flagsSelect, VA { Q_UNUSED(flagsSelect); Q_UNUSED(varID); + QAccessibleInterface *accessible = accessibleInterface(); accessibleDebugClientCalls(accessible); - if (!accessible->isValid()) + if (!accessible) return E_FAIL; bool res = false; @@ -1141,17 +1106,17 @@ HRESULT STDMETHODCALLTYPE QWindowsMsaaAccessible::accSelect(long flagsSelect, VA ### and if there are no ia2 interfaces we should do nothing?? if (flagsSelect & SELFLAG_TAKEFOCUS) - res = accessible->doAction(SetFocus, varID.lVal, QVariantList()); + res = accessible()->doAction(SetFocus, varID.lVal, QVariantList()); if (flagsSelect & SELFLAG_TAKESELECTION) { - accessible->doAction(ClearSelection, 0, QVariantList()); - res = accessible->doAction(AddToSelection, varID.lVal, QVariantList()); + accessible()->doAction(ClearSelection, 0, QVariantList()); + res = accessible()->doAction(AddToSelection, varID.lVal, QVariantList()); } if (flagsSelect & SELFLAG_EXTENDSELECTION) - res = accessible->doAction(ExtendSelection, varID.lVal, QVariantList()); + res = accessible()->doAction(ExtendSelection, varID.lVal, QVariantList()); if (flagsSelect & SELFLAG_ADDSELECTION) - res = accessible->doAction(AddToSelection, varID.lVal, QVariantList()); + res = accessible()->doAction(AddToSelection, varID.lVal, QVariantList()); if (flagsSelect & SELFLAG_REMOVESELECTION) - res = accessible->doAction(RemoveSelection, varID.lVal, QVariantList()); + res = accessible()->doAction(RemoveSelection, varID.lVal, QVariantList()); */ return res ? S_OK : S_FALSE; } @@ -1174,15 +1139,15 @@ HRESULT STDMETHODCALLTYPE QWindowsMsaaAccessible::accSelect(long flagsSelect, VA */ HRESULT STDMETHODCALLTYPE QWindowsMsaaAccessible::get_accFocus(VARIANT *pvarID) { + QAccessibleInterface *accessible = accessibleInterface(); accessibleDebugClientCalls(accessible); - if (!accessible->isValid()) + if (!accessible) return E_FAIL; if (QAccessibleInterface *acc = accessible->focusChild()) { - if (compareAccessible(acc, accessible)) { + if (acc == accessible) { (*pvarID).vt = VT_I4; (*pvarID).lVal = CHILDID_SELF; - delete acc; return S_OK; } else { if (IAccessible *iface = QWindowsAccessibility::wrap(acc)) { @@ -1191,7 +1156,6 @@ HRESULT STDMETHODCALLTYPE QWindowsMsaaAccessible::get_accFocus(VARIANT *pvarID) return S_OK; } } - delete acc; } (*pvarID).vt = VT_EMPTY; return S_FALSE; @@ -1199,8 +1163,9 @@ HRESULT STDMETHODCALLTYPE QWindowsMsaaAccessible::get_accFocus(VARIANT *pvarID) HRESULT STDMETHODCALLTYPE QWindowsMsaaAccessible::get_accSelection(VARIANT *pvarChildren) { + QAccessibleInterface *accessible = accessibleInterface(); accessibleDebugClientCalls(accessible); - if (!accessible->isValid()) + if (!accessible) return E_FAIL; int cc = accessible->childCount(); @@ -1211,7 +1176,6 @@ HRESULT STDMETHODCALLTYPE QWindowsMsaaAccessible::get_accSelection(VARIANT *pvar QAccessibleInterface *child = accessible->child(i); if (child) { isSelected = child->state().selected; - delete child; } if (isSelected) sel[selIndex++] = i+1; @@ -1241,11 +1205,10 @@ HRESULT STDMETHODCALLTYPE QWindowsMsaaAccessible::get_accSelection(VARIANT *pvar HRESULT STDMETHODCALLTYPE QWindowsMsaaAccessible::GetWindow(HWND *phwnd) { *phwnd = 0; + QAccessibleInterface *accessible = accessibleInterface(); accessibleDebugClientCalls(accessible); - if (!accessible->isValid()) + if (!accessible) return E_FAIL; - if (!accessible->isValid()) - return E_UNEXPECTED; QWindow *window = QWindowsAccessibility::windowHelper(accessible); if (!window) diff --git a/src/plugins/platforms/windows/accessible/qwindowsmsaaaccessible.h b/src/plugins/platforms/windows/accessible/qwindowsmsaaaccessible.h index ecb2e2bc18..ef17acf3e9 100644 --- a/src/plugins/platforms/windows/accessible/qwindowsmsaaaccessible.h +++ b/src/plugins/platforms/windows/accessible/qwindowsmsaaaccessible.h @@ -76,8 +76,6 @@ void accessibleDebugClientCalls_helper(const char* funcName, const QAccessibleIn # define accessibleDebugClientCalls(iface) #endif -typedef QSharedPointer<QAccessibleInterface> QAIPointer; - QWindow *window_helper(const QAccessibleInterface *iface); /**************************************************************\ @@ -93,14 +91,13 @@ class QWindowsMsaaAccessible : public { public: QWindowsMsaaAccessible(QAccessibleInterface *a) - : accessible(a) - , ref(0) + : ref(0) { + id = QAccessible::uniqueId(a); } virtual ~QWindowsMsaaAccessible() { - delete accessible; } /* IUnknown */ @@ -146,11 +143,23 @@ public: protected: virtual QByteArray IIDToString(REFIID id); - QAccessibleInterface *accessible; + QAccessible::Id id; + + QAccessibleInterface *accessibleInterface() const + { + QAccessibleInterface *iface = QAccessible::accessibleInterface(id); + if (iface && iface->isValid()) + return iface; + return 0; + } - QAIPointer childPointer(VARIANT varID) + QAccessibleInterface *childPointer(VARIANT varID) { - return QAIPointer(accessible->child(varID.lVal - 1)); + // -1 since windows API always uses 1 for the first child + QAccessibleInterface *iface = accessibleInterface(); + if (iface) + return accessibleInterface()->child(varID.lVal - 1); + return 0; } private: diff --git a/src/widgets/itemviews/qtreeview_p.h b/src/widgets/itemviews/qtreeview_p.h index a687d4665d..90e83cb58c 100644 --- a/src/widgets/itemviews/qtreeview_p.h +++ b/src/widgets/itemviews/qtreeview_p.h @@ -229,7 +229,7 @@ public: { viewItems[item].height = 0; } inline int accessibleTable2Index(const QModelIndex &index) const { - return (viewIndex(index) + (header ? 1 : 0)) * model->columnCount()+index.column() + 1; + return (viewIndex(index) + (header ? 1 : 0)) * model->columnCount()+index.column(); } // used for spanning rows diff --git a/src/widgets/styles/qstylehelper.cpp b/src/widgets/styles/qstylehelper.cpp index 33a422fdd4..fc73488154 100644 --- a/src/widgets/styles/qstylehelper.cpp +++ b/src/widgets/styles/qstylehelper.cpp @@ -92,7 +92,6 @@ bool isInstanceOf(QObject *obj, QAccessible::Role role) bool match = false; QAccessibleInterface *iface = QAccessible::queryAccessibleInterface(obj); match = iface && iface->role() == role; - delete iface; return match; } |