source: trunk/src/gui/accessible/qaccessible_mac_p.h@ 187

Last change on this file since 187 was 2, checked in by Dmitry A. Kuminov, 16 years ago

Initially imported qt-all-opensource-src-4.5.1 from Trolltech.

File size: 12.9 KB
Line 
1/****************************************************************************
2**
3** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
4** Contact: Qt Software Information ([email protected])
5**
6** This file is part of the QtGui module of the Qt Toolkit.
7**
8** $QT_BEGIN_LICENSE:LGPL$
9** Commercial Usage
10** Licensees holding valid Qt Commercial licenses may use this file in
11** accordance with the Qt Commercial License Agreement provided with the
12** Software or, alternatively, in accordance with the terms contained in
13** a written agreement between you and Nokia.
14**
15** GNU Lesser General Public License Usage
16** Alternatively, this file may be used under the terms of the GNU Lesser
17** General Public License version 2.1 as published by the Free Software
18** Foundation and appearing in the file LICENSE.LGPL included in the
19** packaging of this file. Please review the following information to
20** ensure the GNU Lesser General Public License version 2.1 requirements
21** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
22**
23** In addition, as a special exception, Nokia gives you certain
24** additional rights. These rights are described in the Nokia Qt LGPL
25** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
26** package.
27**
28** GNU General Public License Usage
29** Alternatively, this file may be used under the terms of the GNU
30** General Public License version 3.0 as published by the Free Software
31** Foundation and appearing in the file LICENSE.GPL included in the
32** packaging of this file. Please review the following information to
33** ensure the GNU General Public License version 3.0 requirements will be
34** met: http://www.gnu.org/copyleft/gpl.html.
35**
36** If you are unsure which license is appropriate for your use, please
37** contact the sales department at [email protected].
38** $QT_END_LICENSE$
39**
40****************************************************************************/
41
42#ifndef QACCESSIBLE_MAC_P_H
43#define QACCESSIBLE_MAC_P_H
44
45//
46// W A R N I N G
47// -------------
48//
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.
52//
53// We mean it.
54//
55//
56
57#include <qglobal.h>
58#include <private/qt_mac_p.h>
59#include <qaccessible.h>
60#include <qwidget.h>
61#include <qdebug.h>
62
63//#define Q_ACCESSIBLE_MAC_DEBUG
64
65QT_BEGIN_NAMESPACE
66
67/*
68 QAccessibleInterfaceWrapper wraps QAccessibleInterface and adds
69 a ref count. QAccessibleInterfaceWrapper is a "by-value" class.
70*/
71class Q_AUTOTEST_EXPORT QAccessibleInterfaceWrapper
72{
73public:
74 QAccessibleInterfaceWrapper()
75 : interface(0), childrenIsRegistered(new bool(false)), refCount(new int(1)) { }
76
77 QAccessibleInterfaceWrapper(QAccessibleInterface *interface)
78 :interface(interface), childrenIsRegistered(new bool(false)), refCount(new int(1)) { }
79
80 ~QAccessibleInterfaceWrapper()
81 {
82 if (--(*refCount) == 0) {
83 delete interface;
84 delete refCount;
85 delete childrenIsRegistered;
86 }
87 }
88
89 QAccessibleInterfaceWrapper(const QAccessibleInterfaceWrapper &other)
90 :interface(other.interface), childrenIsRegistered(other.childrenIsRegistered), refCount(other.refCount)
91 {
92 ++(*refCount);
93 }
94
95 void operator=(const QAccessibleInterfaceWrapper &other)
96 {
97 if (other.interface == interface)
98 return;
99
100 if (--(*refCount) == 0) {
101 delete interface;
102 delete refCount;
103 delete childrenIsRegistered;
104 }
105
106 interface = other.interface;
107 childrenIsRegistered = other.childrenIsRegistered;
108 refCount = other.refCount;
109 ++(*refCount);
110 }
111
112 QAccessibleInterface *interface;
113 bool *childrenIsRegistered;
114private:
115 int *refCount;
116};
117
118/*
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.
123
124 It has the same API as QAccessibleInterface, minus the child parameter
125 in the funcitons.
126*/
127class Q_AUTOTEST_EXPORT QAInterface : public QAccessible
128{
129public:
130 QAInterface()
131 : base(QAccessibleInterfaceWrapper())
132 { }
133
134 QAInterface(QAccessibleInterface *interface, int child = 0)
135 {
136 if (interface == 0 || child > interface->childCount()) {
137 base = QAccessibleInterfaceWrapper();
138 } else {
139 base = QAccessibleInterfaceWrapper(interface);
140 m_cachedObject = interface->object();
141 this->child = child;
142 }
143 }
144
145 QAInterface(QAccessibleInterfaceWrapper wrapper, int child = 0)
146 :base(wrapper), m_cachedObject(wrapper.interface->object()), child(child)
147 { }
148
149 QAInterface(const QAInterface &other, int child)
150 {
151 if (other.isValid() == false || child > other.childCount()) {
152 base = QAccessibleInterfaceWrapper();
153 } else {
154 base = other.base;
155 m_cachedObject = other.m_cachedObject;
156 this->child = child;
157 }
158 }
159
160 bool operator==(const QAInterface &other) const;
161 bool operator!=(const QAInterface &other) const;
162
163 inline QString actionText (int action, Text text) const
164 { return base.interface->actionText(action, text, child); }
165
166 QAInterface childAt(int x, int y) const
167 {
168 if (!checkValid())
169 return QAInterface();
170
171 const int foundChild = base.interface->childAt(x, y);
172
173 if (foundChild == -1)
174 return QAInterface();
175
176 if (child == 0)
177 return navigate(QAccessible::Child, foundChild);
178
179 if (foundChild == child)
180 return *this;
181 return QAInterface();
182 }
183
184 int indexOfChild(const QAInterface &child) const
185 {
186 if (!checkValid())
187 return -1;
188
189 if (*this != child.parent())
190 return -1;
191
192 if (object() == child.object())
193 return child.id();
194
195 return base.interface->indexOfChild(child.base.interface);
196 }
197
198 inline int childCount() const
199 {
200 if (!checkValid())
201 return 0;
202
203 if (child != 0)
204 return 0;
205 return base.interface->childCount();
206 }
207
208 QList<QAInterface> children() const
209 {
210 if (!checkValid())
211 return QList<QAInterface>();
212
213 QList<QAInterface> children;
214 for (int i = 1; i <= childCount(); ++i) {
215 children.append(navigate(QAccessible::Child, i));
216 }
217 return children;
218 }
219
220 QAInterface childAt(int index) const
221 {
222 return navigate(QAccessible::Child, index);
223 }
224
225 inline void doAction(int action, const QVariantList &params = QVariantList()) const
226 {
227 if (!checkValid())
228 return;
229
230 base.interface->doAction(action, child, params);
231 }
232
233 QAInterface navigate(RelationFlag relation, int entry) const;
234
235 inline QObject * object() const
236 {
237 if (!checkValid())
238 return 0;
239
240 return base.interface->object();
241 }
242
243 QAInterface objectInterface() const
244 {
245 if (!checkValid())
246 return QAInterface();
247
248 QObject *obj = object();
249 QAInterface current = *this;
250 while (obj == 0)
251 {
252 QAInterface parent = current.parent();
253 if (parent.isValid() == false)
254 break;
255 obj = parent.object();
256 current = parent;
257 }
258 return current;
259 }
260
261 inline HIObjectRef hiObject() const
262 {
263 if (!checkValid())
264 return 0;
265 QWidget * const widget = qobject_cast<QWidget * const>(object());
266 if (widget)
267 return (HIObjectRef)widget->winId();
268 else
269 return 0;
270 }
271
272 inline QObject * cachedObject() const
273 {
274 if (!checkValid())
275 return 0;
276 return m_cachedObject;
277 }
278
279 inline QRect rect() const
280 {
281 if (!checkValid())
282 return QRect();
283 return base.interface->rect(child);
284 }
285
286 inline Role role() const
287 {
288 if (!checkValid())
289 return QAccessible::NoRole;
290 return base.interface->role(child);
291 }
292
293 inline void setText(Text t, const QString &text) const
294 {
295 if (!checkValid())
296 return;
297 base.interface->setText(t, child, text);
298 }
299
300 inline State state() const
301 {
302 if (!checkValid())
303 return 0;
304 return base.interface->state(child);
305 }
306
307 inline QString text (Text text) const
308 {
309 if (!checkValid())
310 return QString();
311 return base.interface->text(text, child);
312 }
313
314 inline QString value() const
315 { return text(QAccessible::Value); }
316
317 inline QString name() const
318 { return text(QAccessible::Name); }
319
320 inline int userActionCount() const
321 {
322 if (!checkValid())
323 return 0;
324 return base.interface->userActionCount(child);
325 }
326
327 inline QString className() const
328 {
329 if (!checkValid())
330 return QString();
331 return QLatin1String(base.interface->object()->metaObject()->className());
332 }
333
334 inline bool isHIView() const
335 { return (child == 0 && object() != 0); }
336
337 inline int id() const
338 { return child; }
339
340 inline bool isValid() const
341 {
342 return (base.interface != 0 && base.interface->isValid());
343 }
344
345 QAInterface parent() const
346 { return navigate(QAccessible::Ancestor, 1); }
347
348 QAccessibleInterfaceWrapper interfaceWrapper() const
349 { return base; }
350
351protected:
352 bool checkValid() const
353 {
354 const bool valid = isValid();
355#ifdef Q_ACCESSIBLE_MAC_DEBUG
356 if (!valid)
357 qFatal("QAccessible_mac: tried to use invalid interface.");
358#endif
359 return valid;
360 }
361
362 QAccessibleInterfaceWrapper base;
363 QObject *m_cachedObject;
364 int child;
365};
366
367Q_AUTOTEST_EXPORT QDebug operator<<(QDebug debug, const QAInterface &interface);
368
369/*
370 QAElement is a thin wrapper around an AXUIElementRef that automates
371 the ref-counting.
372*/
373class Q_AUTOTEST_EXPORT QAElement
374{
375public:
376 QAElement();
377 explicit QAElement(AXUIElementRef elementRef);
378 QAElement(const QAElement &element);
379 QAElement(HIObjectRef, int child);
380 ~QAElement();
381
382 inline HIObjectRef object() const
383 {
384#ifndef Q_WS_MAC64
385 return AXUIElementGetHIObject(elementRef);
386#else
387 return 0;
388#endif
389 }
390
391 inline int id() const
392 {
393 UInt64 theId;
394#ifndef QT_MAC_USE_COCOA
395 AXUIElementGetIdentifier(elementRef, &theId);
396#else
397 theId = 0;
398#endif
399 return theId;
400 }
401
402 inline AXUIElementRef element() const
403 {
404 return elementRef;
405 }
406
407 inline bool isValid() const
408 {
409 return (elementRef != 0);
410 }
411
412 void operator=(const QAElement &other);
413 bool operator==(const QAElement &other) const;
414private:
415 AXUIElementRef elementRef;
416};
417
418
419class QInterfaceFactory
420{
421public:
422 virtual QAInterface interface(UInt64 identifier) = 0;
423 virtual QAElement element(int id) = 0;
424 virtual QAElement element(const QAInterface &interface)
425 {
426 return element(interface.id());
427 }
428 virtual void registerChildren() = 0;
429 virtual ~QInterfaceFactory() {}
430};
431
432/*
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 provies lookup funcitons
436 that translates between these to items.
437
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.
441
442 QAccessibleHierarchyManager receives QObject::destroyed() signals and deletes
443 the accessibility objects for destroyed objects.
444*/
445class Q_AUTOTEST_EXPORT QAccessibleHierarchyManager : public QObject
446{
447Q_OBJECT
448public:
449 ~QAccessibleHierarchyManager() { reset(); }
450 static QAccessibleHierarchyManager *instance();
451 void reset();
452
453 QAElement registerInterface(QObject *object, int child);
454 QAElement registerInterface(const QAInterface &interface);
455 void registerInterface(QObject *object, HIObjectRef hiobject, QInterfaceFactory *interfaceFactory);
456
457 void registerChildren(const QAInterface &interface);
458
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);
463private slots:
464 void objectDestroyed(QObject *);
465private:
466 typedef QHash<QObject *, QInterfaceFactory *> QObjectElementHash;
467 typedef QHash<HIObjectRef, QInterfaceFactory *> HIObjectInterfaceHash;
468 typedef QHash<QObject *, HIObjectRef> QObjectHIObjectHash;
469
470 QObjectElementHash qobjectElementHash;
471 HIObjectInterfaceHash hiobjectInterfaceHash;
472 QObjectHIObjectHash qobjectHiobjectHash;
473};
474
475Q_AUTOTEST_EXPORT bool isItInteresting(const QAInterface &interface);
476
477QT_END_NAMESPACE
478
479#endif
Note: See TracBrowser for help on using the repository browser.