Remove a ###
[profile/ivi/qtbase.git] / src / gui / accessible / qaccessible_mac_p.h
1 /****************************************************************************
2 **
3 ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
4 ** All rights reserved.
5 ** Contact: Nokia Corporation (qt-info@nokia.com)
6 **
7 ** This file is part of the QtGui module of the Qt Toolkit.
8 **
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.
17 **
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.
21 **
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.
29 **
30 ** Other Usage
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.
33 **
34 **
35 **
36 **
37 **
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
65 QT_BEGIN_NAMESPACE
66
67 /*
68     QAccessibleInterfaceWrapper wraps QAccessibleInterface and adds
69     a ref count. QAccessibleInterfaceWrapper is a "by-value" class.
70 */
71 class Q_AUTOTEST_EXPORT QAccessibleInterfaceWrapper
72 {
73 public:
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;
114 private:
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 functions.
126 */
127 class Q_AUTOTEST_EXPORT QAInterface : public QAccessible
128 {
129 public:
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
351 protected:
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
367 Q_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 */
373 class Q_AUTOTEST_EXPORT QAElement
374 {
375 public:
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;
414 private:
415     AXUIElementRef elementRef;
416 };
417
418
419 class QInterfaceFactory
420 {
421 public:
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 provides lookup functions
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 */
445 class Q_AUTOTEST_EXPORT QAccessibleHierarchyManager : public QObject
446 {
447 Q_OBJECT
448 public:
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);
463 private slots:
464     void objectDestroyed(QObject *);
465 private:
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
475 Q_AUTOTEST_EXPORT bool isItInteresting(const QAInterface &interface);
476
477 QT_END_NAMESPACE
478
479 #endif