From b2ec0da95641d9cec006fa9699e6d082ad35db0b Mon Sep 17 00:00:00 2001 From: Frederik Gladhorn Date: Thu, 3 Jan 2013 17:18:40 +0100 Subject: Cache QAccessibleInterfaces. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Since there already is a one-to-one relationship between QObject and QAccessibleInterface it makes little sense to create and destroy the interfaces on each call to queryAccessibleInterface. Add a cache and keep created interfaces around for the lifetime of the corresponding QObject. This changes the memory management rules: accessible interfaces must no longer be deleted. If you get an QAccessibleIntrface pointer that pointer will stay valid as long as the corresponding QObject is not deleted. This also re-enables accessibility for Mac. We limit the range of the IDs so that they are useable for Windows directly. That means we can get rid of the event cache there. This is based on: Iebf2f374916fc70a9dd29e95f45a6444b85f6cee Change-Id: I9fe6531812c0dbc5b41101ac05830a6dd75e13a3 Reviewed-by: Morten Johan Sørvig --- src/gui/accessible/accessible.pri | 2 + src/gui/accessible/qaccessible.cpp | 106 ++++++- src/gui/accessible/qaccessible.h | 20 +- src/gui/accessible/qaccessible2_p.h | 2 + src/gui/accessible/qaccessiblecache.cpp | 116 ++++++++ src/gui/accessible/qaccessiblecache_p.h | 78 ++++++ src/gui/accessible/qaccessibleobject.cpp | 6 +- .../linuxaccessibility/atspiadaptor.cpp | 235 ++++++---------- .../linuxaccessibility/atspiadaptor_p.h | 49 ++-- src/plugins/accessible/widgets/complexwidgets.cpp | 12 +- src/plugins/accessible/widgets/complexwidgets.h | 3 + src/plugins/accessible/widgets/itemviews.cpp | 309 +++++++++++++++------ src/plugins/accessible/widgets/itemviews.h | 23 +- src/plugins/accessible/widgets/main.cpp | 8 - src/plugins/accessible/widgets/qaccessiblemenu.cpp | 24 +- .../accessible/widgets/qaccessiblewidgets.cpp | 1 - src/plugins/platforms/cocoa/cocoa.pro | 3 - src/plugins/platforms/cocoa/qcocoaaccessibility.h | 7 +- src/plugins/platforms/cocoa/qcocoaaccessibility.mm | 15 +- .../platforms/cocoa/qcocoaaccessibilityelement.h | 12 +- .../platforms/cocoa/qcocoaaccessibilityelement.mm | 119 ++++---- src/plugins/platforms/cocoa/qcocoaintegration.h | 2 +- src/plugins/platforms/cocoa/qcocoaintegration.mm | 4 +- .../platforms/cocoa/qnsviewaccessibility.mm | 13 +- .../platforms/windows/accessible/iaccessible2.cpp | 228 +++++++++------ .../platforms/windows/accessible/iaccessible2.h | 14 +- .../windows/accessible/qwindowsaccessibility.cpp | 44 +-- .../windows/accessible/qwindowsaccessibility.h | 2 - .../windows/accessible/qwindowsmsaaaccessible.cpp | 173 +++++------- .../windows/accessible/qwindowsmsaaaccessible.h | 25 +- src/widgets/itemviews/qtreeview_p.h | 2 +- src/widgets/styles/qstylehelper.cpp | 1 - 32 files changed, 1020 insertions(+), 638 deletions(-) create mode 100644 src/gui/accessible/qaccessiblecache.cpp create mode 100644 src/gui/accessible/qaccessiblecache_p.h (limited to 'src') 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,21 +619,83 @@ 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(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 #include #include #include @@ -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 +#include +#include + +#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 idToInterface; + mutable QHash 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 " \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(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(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 RelationPair; QVector 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 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(object); - if (!m_handledObjects.contains(uintptr) || m_handledObjects.value(uintptr) == 0) - m_handledObjects[uintptr] = QPointer(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(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(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(); @@ -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 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 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 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 > 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 #include + 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 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 #include #include -#include #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 QAccessibleTable::selectedCells() const QList 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 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(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(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(iface); + if (cell->index >= event->firstRow()) { + cell->index += newRows; + } + } else if (event->modelChangeType() == QAccessibleTableModelChangeEvent::ColumnsInserted + && iface->role() == QAccessible::ColumnHeader) { + QAccessibleTableHeaderCell *cell = static_cast(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(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(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(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 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(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(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 QAccessibleTableCell::rowHeaderCells() const { QList headerCell; if (verticalHeader()) { + // FIXME headerCell.append(new QAccessibleTableHeaderCell(view, m_index.row(), Qt::Vertical)); } return headerCell; @@ -726,6 +871,7 @@ QList QAccessibleTableCell::columnHeaderCells() const { QList 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 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 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(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 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 view; int index; Qt::Orientation orientation; @@ -273,8 +277,9 @@ public: QAccessibleInterface *child(int) const { return 0; } + private: - QAbstractItemView *view; + QPointer 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(widget->parentWidget())) { - if (qobject_cast(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(w) || qobject_cast(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 #include - -#ifndef QT_NO_COCOA_ACCESSIBILITY - #include 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 #include -#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 #import -#ifndef QT_NO_COCOA_ACCESSIBILITY +#import @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 -#ifndef QT_NO_COCOA_ACCESSIBILITY - -static QAccessibleInterface *acast(void *ptr) -{ - return reinterpret_cast(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 mInputContext; -#ifndef QT_NO_COCOA_ACCESSIBILITY +#ifndef QT_NO_ACCESSIBILITY QScopedPointer mAccessibility; #endif QScopedPointer 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 -#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 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 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 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 RelationEntry; @@ -1588,37 +1667,6 @@ HRESULT QWindowsIA2Accessible::wrapListOfCells(const QList 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 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(0); + QAccessibleInterface *accessible = accessibleInterface(); + return accessible ? accessible->textInterface() : static_cast(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 &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> > 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(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 QWindowsAccessibility::getCachedObject(int entryId) -{ - QPair, 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 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 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 RelationPair; QVector 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 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; } -- cgit v1.2.3