1 /****************************************************************************
3 ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
4 ** All rights reserved.
5 ** Contact: Nokia Corporation (qt-info@nokia.com)
7 ** This file is part of the QtGui module of the Qt Toolkit.
9 ** $QT_BEGIN_LICENSE:LGPL$
10 ** GNU Lesser General Public License Usage
11 ** This file may be used under the terms of the GNU Lesser General Public
12 ** License version 2.1 as published by the Free Software Foundation and
13 ** appearing in the file LICENSE.LGPL included in the packaging of this
14 ** file. Please review the following information to ensure the GNU Lesser
15 ** General Public License version 2.1 requirements will be met:
16 ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
18 ** In addition, as a special exception, Nokia gives you certain additional
19 ** rights. These rights are described in the Nokia Qt LGPL Exception
20 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
22 ** GNU General Public License Usage
23 ** Alternatively, this file may be used under the terms of the GNU General
24 ** Public License version 3.0 as published by the Free Software Foundation
25 ** and appearing in the file LICENSE.GPL included in the packaging of this
26 ** file. Please review the following information to ensure the GNU General
27 ** Public License version 3.0 requirements will be met:
28 ** http://www.gnu.org/copyleft/gpl.html.
31 ** Alternatively, this file may be used in accordance with the terms and
32 ** conditions contained in a signed written agreement between you and Nokia.
40 ****************************************************************************/
42 #ifndef QACCESSIBLE_MAC_P_H
43 #define QACCESSIBLE_MAC_P_H
49 // This file is not part of the Qt API. It exists purely as an
50 // implementation detail. This header file may change from version to
51 // version without notice, or even be removed.
58 #include <private/qt_mac_p.h>
59 #include <qaccessible.h>
63 //#define Q_ACCESSIBLE_MAC_DEBUG
68 QAccessibleInterfaceWrapper wraps QAccessibleInterface and adds
69 a ref count. QAccessibleInterfaceWrapper is a "by-value" class.
71 class Q_AUTOTEST_EXPORT QAccessibleInterfaceWrapper
74 QAccessibleInterfaceWrapper()
75 : interface(0), childrenIsRegistered(new bool(false)), refCount(new int(1)) { }
77 QAccessibleInterfaceWrapper(QAccessibleInterface *interface)
78 :interface(interface), childrenIsRegistered(new bool(false)), refCount(new int(1)) { }
80 ~QAccessibleInterfaceWrapper()
82 if (--(*refCount) == 0) {
85 delete childrenIsRegistered;
89 QAccessibleInterfaceWrapper(const QAccessibleInterfaceWrapper &other)
90 :interface(other.interface), childrenIsRegistered(other.childrenIsRegistered), refCount(other.refCount)
95 void operator=(const QAccessibleInterfaceWrapper &other)
97 if (other.interface == interface)
100 if (--(*refCount) == 0) {
103 delete childrenIsRegistered;
106 interface = other.interface;
107 childrenIsRegistered = other.childrenIsRegistered;
108 refCount = other.refCount;
112 QAccessibleInterface *interface;
113 bool *childrenIsRegistered;
119 QAInterface represents one accessiblity item. It hides the fact that
120 one QAccessibleInterface may represent more than one item, and it also
121 automates the memory management for QAccessibleInterfaces using the
122 QAccessibleInterfaceWrapper wrapper class.
124 It has the same API as QAccessibleInterface, minus the child parameter
127 class Q_AUTOTEST_EXPORT QAInterface : public QAccessible
131 : base(QAccessibleInterfaceWrapper())
134 QAInterface(QAccessibleInterface *interface, int child = 0)
136 if (interface == 0 || child > interface->childCount()) {
137 base = QAccessibleInterfaceWrapper();
139 base = QAccessibleInterfaceWrapper(interface);
140 m_cachedObject = interface->object();
145 QAInterface(QAccessibleInterfaceWrapper wrapper, int child = 0)
146 :base(wrapper), m_cachedObject(wrapper.interface->object()), child(child)
149 QAInterface(const QAInterface &other, int child)
151 if (other.isValid() == false || child > other.childCount()) {
152 base = QAccessibleInterfaceWrapper();
155 m_cachedObject = other.m_cachedObject;
160 bool operator==(const QAInterface &other) const;
161 bool operator!=(const QAInterface &other) const;
163 inline QString actionText (int action, Text text) const
164 { return base.interface->actionText(action, text, child); }
166 QAInterface childAt(int x, int y) const
169 return QAInterface();
171 const int foundChild = base.interface->childAt(x, y);
173 if (foundChild == -1)
174 return QAInterface();
177 return navigate(QAccessible::Child, foundChild);
179 if (foundChild == child)
181 return QAInterface();
184 int indexOfChild(const QAInterface &child) const
189 if (*this != child.parent())
192 if (object() == child.object())
195 return base.interface->indexOfChild(child.base.interface);
198 inline int childCount() const
205 return base.interface->childCount();
208 QList<QAInterface> children() const
211 return QList<QAInterface>();
213 QList<QAInterface> children;
214 for (int i = 1; i <= childCount(); ++i) {
215 children.append(navigate(QAccessible::Child, i));
220 QAInterface childAt(int index) const
222 return navigate(QAccessible::Child, index);
225 inline void doAction(int action, const QVariantList ¶ms = QVariantList()) const
230 base.interface->doAction(action, child, params);
233 QAInterface navigate(RelationFlag relation, int entry) const;
235 inline QObject * object() const
240 return base.interface->object();
243 QAInterface objectInterface() const
246 return QAInterface();
248 QObject *obj = object();
249 QAInterface current = *this;
252 QAInterface parent = current.parent();
253 if (parent.isValid() == false)
255 obj = parent.object();
261 inline HIObjectRef hiObject() const
265 QWidget * const widget = qobject_cast<QWidget * const>(object());
267 return (HIObjectRef)widget->winId();
272 inline QObject * cachedObject() const
276 return m_cachedObject;
279 inline QRect rect() const
283 return base.interface->rect(child);
286 inline Role role() const
289 return QAccessible::NoRole;
290 return base.interface->role(child);
293 inline void setText(Text t, const QString &text) const
297 base.interface->setText(t, child, text);
300 inline State state() const
304 return base.interface->state(child);
307 inline QString text (Text text) const
311 return base.interface->text(text, child);
314 inline QString value() const
315 { return text(QAccessible::Value); }
317 inline QString name() const
318 { return text(QAccessible::Name); }
320 inline int userActionCount() const
324 return base.interface->userActionCount(child);
327 inline QString className() const
331 return QLatin1String(base.interface->object()->metaObject()->className());
334 inline bool isHIView() const
335 { return (child == 0 && object() != 0); }
337 inline int id() const
340 inline bool isValid() const
342 return (base.interface != 0 && base.interface->isValid());
345 QAInterface parent() const
346 { return navigate(QAccessible::Ancestor, 1); }
348 QAccessibleInterfaceWrapper interfaceWrapper() const
352 bool checkValid() const
354 const bool valid = isValid();
355 #ifdef Q_ACCESSIBLE_MAC_DEBUG
357 qFatal("QAccessible_mac: tried to use invalid interface.");
362 QAccessibleInterfaceWrapper base;
363 QObject *m_cachedObject;
367 Q_AUTOTEST_EXPORT QDebug operator<<(QDebug debug, const QAInterface &interface);
370 QAElement is a thin wrapper around an AXUIElementRef that automates
373 class Q_AUTOTEST_EXPORT QAElement
377 explicit QAElement(AXUIElementRef elementRef);
378 QAElement(const QAElement &element);
379 QAElement(HIObjectRef, int child);
382 inline HIObjectRef object() const
385 return AXUIElementGetHIObject(elementRef);
391 inline int id() const
394 #ifndef QT_MAC_USE_COCOA
395 AXUIElementGetIdentifier(elementRef, &theId);
402 inline AXUIElementRef element() const
407 inline bool isValid() const
409 return (elementRef != 0);
412 void operator=(const QAElement &other);
413 bool operator==(const QAElement &other) const;
415 AXUIElementRef elementRef;
419 class QInterfaceFactory
422 virtual QAInterface interface(UInt64 identifier) = 0;
423 virtual QAElement element(int id) = 0;
424 virtual QAElement element(const QAInterface &interface)
426 return element(interface.id());
428 virtual void registerChildren() = 0;
429 virtual ~QInterfaceFactory() {}
433 QAccessibleHierarchyManager bridges the Mac and Qt accessibility hierarchies.
434 There is a one-to-one relationship between QAElements on the Mac side
435 and QAInterfaces on the Qt side, and this class provides lookup functions
436 that translates between these to items.
438 The identity of a QAInterface is determined by its QAccessibleInterface and
439 child identifier, and the identity of a QAElement is determined by its
440 HIObjectRef and identifier.
442 QAccessibleHierarchyManager receives QObject::destroyed() signals and deletes
443 the accessibility objects for destroyed objects.
445 class Q_AUTOTEST_EXPORT QAccessibleHierarchyManager : public QObject
449 ~QAccessibleHierarchyManager() { reset(); }
450 static QAccessibleHierarchyManager *instance();
453 QAElement registerInterface(QObject *object, int child);
454 QAElement registerInterface(const QAInterface &interface);
455 void registerInterface(QObject *object, HIObjectRef hiobject, QInterfaceFactory *interfaceFactory);
457 void registerChildren(const QAInterface &interface);
459 QAInterface lookup(const AXUIElementRef &element);
460 QAInterface lookup(const QAElement &element);
461 QAElement lookup(const QAInterface &interface);
462 QAElement lookup(QObject * const object, int id);
464 void objectDestroyed(QObject *);
466 typedef QHash<QObject *, QInterfaceFactory *> QObjectElementHash;
467 typedef QHash<HIObjectRef, QInterfaceFactory *> HIObjectInterfaceHash;
468 typedef QHash<QObject *, HIObjectRef> QObjectHIObjectHash;
470 QObjectElementHash qobjectElementHash;
471 HIObjectInterfaceHash hiobjectInterfaceHash;
472 QObjectHIObjectHash qobjectHiobjectHash;
475 Q_AUTOTEST_EXPORT bool isItInteresting(const QAInterface &interface);