Remove a ###
[profile/ivi/qtbase.git] / src / gui / accessible / qaccessible_mac.mm
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 #include "qaccessible.h"
43
44 #ifndef QT_NO_ACCESSIBILITY
45 #include "qaccessible_mac_p.h"
46 #include "qhash.h"
47 #include "qset.h"
48 #include "qpointer.h"
49 #include "qapplication.h"
50 #include "qmainwindow.h"
51 #include "qtextdocument.h"
52 #include "qdebug.h"
53 #include "qabstractslider.h"
54 #include "qsplitter.h"
55 #include "qtabwidget.h"
56 #include "qlistview.h"
57 #include "qtableview.h"
58 #include "qdockwidget.h"
59
60 #include <private/qt_mac_p.h>
61 #include <private/qwidget_p.h>
62 #include <CoreFoundation/CoreFoundation.h>
63
64 QT_BEGIN_NAMESPACE
65
66 /*
67     Set up platform defines. There is a one-to-one correspondence between the
68     Carbon and Cocoa roles and attributes, but the prefix and type changes.
69 */
70 #ifdef QT_MAC_USE_COCOA
71 typedef NSString * const QAXRoleType;
72 #define QAXApplicationRole NSAccessibilityApplicationRole
73 #define QAXButtonRole NSAccessibilityButtonRole
74 #define QAXCancelAction NSAccessibilityCancelAction
75 #define QAXCheckBoxRole NSAccessibilityCheckBoxRole
76 #define QAXChildrenAttribute NSAccessibilityChildrenAttribute
77 #define QAXCloseButtonAttribute NSAccessibilityCloseButtonAttribute
78 #define QAXCloseButtonAttribute NSAccessibilityCloseButtonAttribute
79 #define QAXColumnRole NSAccessibilityColumnRole
80 #define QAXConfirmAction NSAccessibilityConfirmAction
81 #define QAXContentsAttribute NSAccessibilityContentsAttribute
82 #define QAXDecrementAction NSAccessibilityDecrementAction
83 #define QAXDecrementArrowSubrole NSAccessibilityDecrementArrowSubrole
84 #define QAXDecrementPageSubrole NSAccessibilityDecrementPageSubrole
85 #define QAXDescriptionAttribute NSAccessibilityDescriptionAttribute
86 #define QAXEnabledAttribute NSAccessibilityEnabledAttribute
87 #define QAXExpandedAttribute NSAccessibilityExpandedAttribute
88 #define QAXFocusedAttribute NSAccessibilityFocusedAttribute
89 #define QAXFocusedUIElementChangedNotification NSAccessibilityFocusedUIElementChangedNotification
90 #define QAXFocusedWindowChangedNotification NSAccessibilityFocusedWindowChangedNotification
91 #define QAXGroupRole NSAccessibilityGroupRole
92 #define QAXGrowAreaAttribute NSAccessibilityGrowAreaAttribute
93 #define QAXGrowAreaRole NSAccessibilityGrowAreaRole
94 #define QAXHelpAttribute NSAccessibilityHelpAttribute
95 #define QAXHorizontalOrientationValue NSAccessibilityHorizontalOrientationValue
96 #define QAXHorizontalScrollBarAttribute NSAccessibilityHorizontalScrollBarAttribute
97 #define QAXIncrementAction NSAccessibilityIncrementAction
98 #define QAXIncrementArrowSubrole NSAccessibilityIncrementArrowSubrole
99 #define QAXIncrementPageSubrole NSAccessibilityIncrementPageSubrole
100 #define QAXIncrementorRole NSAccessibilityIncrementorRole
101 #define QAXLinkedUIElementsAttribute NSAccessibilityLinkedUIElementsAttribute
102 #define QAXListRole NSAccessibilityListRole
103 #define QAXMainAttribute NSAccessibilityMainAttribute
104 #define QAXMaxValueAttribute NSAccessibilityMaxValueAttribute
105 #define QAXMenuBarRole NSAccessibilityMenuBarRole
106 #define QAXMenuButtonRole NSAccessibilityMenuButtonRole
107 #define QAXMenuClosedNotification NSAccessibilityMenuClosedNotification
108 #define QAXMenuItemRole NSAccessibilityMenuItemRole
109 #define QAXMenuOpenedNotification NSAccessibilityMenuOpenedNotification
110 #define QAXMenuRole NSAccessibilityMenuRole
111 #define QAXMinValueAttribute NSAccessibilityMinValueAttribute
112 #define QAXMinimizeButtonAttribute NSAccessibilityMinimizeButtonAttribute
113 #define QAXMinimizedAttribute NSAccessibilityMinimizedAttribute
114 #define QAXNextContentsAttribute NSAccessibilityNextContentsAttribute
115 #define QAXOrientationAttribute NSAccessibilityOrientationAttribute
116 #define QAXParentAttribute NSAccessibilityParentAttribute
117 #define QAXPickAction NSAccessibilityPickAction
118 #define QAXPopUpButtonRole NSAccessibilityPopUpButtonRole
119 #define QAXPositionAttribute NSAccessibilityPositionAttribute
120 #define QAXPressAction NSAccessibilityPressAction
121 #define QAXPreviousContentsAttribute NSAccessibilityPreviousContentsAttribute
122 #define QAXProgressIndicatorRole NSAccessibilityProgressIndicatorRole
123 #define QAXRadioButtonRole NSAccessibilityRadioButtonRole
124 #define QAXRoleAttribute NSAccessibilityRoleAttribute
125 #define QAXRoleDescriptionAttribute NSAccessibilityRoleDescriptionAttribute
126 #define QAXRowRole NSAccessibilityRowRole
127 #define QAXRowsAttribute NSAccessibilityRowsAttribute
128 #define QAXScrollAreaRole NSAccessibilityScrollAreaRole
129 #define QAXScrollBarRole NSAccessibilityScrollBarRole
130 #define QAXSelectedAttribute NSAccessibilitySelectedAttribute
131 #define QAXSelectedChildrenAttribute NSAccessibilitySelectedChildrenAttribute
132 #define QAXSelectedRowsAttribute NSAccessibilitySelectedRowsAttribute
133 #define QAXSizeAttribute NSAccessibilitySizeAttribute
134 #define QAXSliderRole NSAccessibilitySliderRole
135 #define QAXSplitGroupRole NSAccessibilitySplitGroupRole
136 #define QAXSplitterRole NSAccessibilitySplitterRole
137 #define QAXSplittersAttribute NSAccessibilitySplittersAttribute
138 #define QAXStaticTextRole NSAccessibilityStaticTextRole
139 #define QAXSubroleAttribute NSAccessibilitySubroleAttribute
140 #define QAXSubroleAttribute NSAccessibilitySubroleAttribute
141 #define QAXTabGroupRole NSAccessibilityTabGroupRole
142 #define QAXTableRole NSAccessibilityTableRole
143 #define QAXTabsAttribute NSAccessibilityTabsAttribute
144 #define QAXTextFieldRole NSAccessibilityTextFieldRole
145 #define QAXTitleAttribute NSAccessibilityTitleAttribute
146 #define QAXTitleUIElementAttribute NSAccessibilityTitleUIElementAttribute
147 #define QAXToolbarButtonAttribute NSAccessibilityToolbarButtonAttribute
148 #define QAXToolbarRole NSAccessibilityToolbarRole
149 #define QAXTopLevelUIElementAttribute NSAccessibilityTopLevelUIElementAttribute
150 #define QAXUnknownRole NSAccessibilityUnknownRole
151 #define QAXValueAttribute NSAccessibilityValueAttribute
152 #define QAXValueChangedNotification NSAccessibilityValueChangedNotification
153 #define QAXValueIndicatorRole NSAccessibilityValueIndicatorRole
154 #define QAXVerticalOrientationValue NSAccessibilityVerticalOrientationValue
155 #define QAXVerticalScrollBarAttribute NSAccessibilityVerticalScrollBarAttribute
156 #define QAXVisibleRowsAttribute NSAccessibilityVisibleRowsAttribute
157 #define QAXWindowAttribute NSAccessibilityWindowAttribute
158 #define QAXWindowCreatedNotification NSAccessibilityWindowCreatedNotification
159 #define QAXWindowMovedNotification NSAccessibilityWindowMovedNotification
160 #define QAXWindowRole NSAccessibilityWindowRole
161 #define QAXZoomButtonAttribute NSAccessibilityZoomButtonAttribute
162 #else
163 typedef CFStringRef const QAXRoleType;
164 #define QAXApplicationRole kAXApplicationRole
165 #define QAXButtonRole kAXButtonRole
166 #define QAXCancelAction kAXCancelAction
167 #define QAXCheckBoxRole kAXCheckBoxRole
168 #define QAXChildrenAttribute kAXChildrenAttribute
169 #define QAXCloseButtonAttribute kAXCloseButtonAttribute
170 #define QAXColumnRole kAXColumnRole
171 #define QAXConfirmAction kAXConfirmAction
172 #define QAXContentsAttribute kAXContentsAttribute
173 #define QAXDecrementAction kAXDecrementAction
174 #define QAXDecrementArrowSubrole kAXDecrementArrowSubrole
175 #define QAXDecrementPageSubrole kAXDecrementPageSubrole
176 #define QAXDescriptionAttribute kAXDescriptionAttribute
177 #define QAXEnabledAttribute kAXEnabledAttribute
178 #define QAXExpandedAttribute kAXExpandedAttribute
179 #define QAXFocusedAttribute kAXFocusedAttribute
180 #define QAXFocusedUIElementChangedNotification kAXFocusedUIElementChangedNotification
181 #define QAXFocusedWindowChangedNotification kAXFocusedWindowChangedNotification
182 #define QAXGroupRole kAXGroupRole
183 #define QAXGrowAreaAttribute kAXGrowAreaAttribute
184 #define QAXGrowAreaRole kAXGrowAreaRole
185 #define QAXHelpAttribute kAXHelpAttribute
186 #define QAXHorizontalOrientationValue kAXHorizontalOrientationValue
187 #define QAXHorizontalScrollBarAttribute kAXHorizontalScrollBarAttribute
188 #define QAXIncrementAction kAXIncrementAction
189 #define QAXIncrementArrowSubrole kAXIncrementArrowSubrole
190 #define QAXIncrementPageSubrole kAXIncrementPageSubrole
191 #define QAXIncrementorRole kAXIncrementorRole
192 #define QAXLinkedUIElementsAttribute kAXLinkedUIElementsAttribute
193 #define QAXListRole kAXListRole
194 #define QAXMainAttribute kAXMainAttribute
195 #define QAXMaxValueAttribute kAXMaxValueAttribute
196 #define QAXMenuBarRole kAXMenuBarRole
197 #define QAXMenuButtonRole kAXMenuButtonRole
198 #define QAXMenuClosedNotification kAXMenuClosedNotification
199 #define QAXMenuItemRole kAXMenuItemRole
200 #define QAXMenuOpenedNotification kAXMenuOpenedNotification
201 #define QAXMenuRole kAXMenuRole
202 #define QAXMinValueAttribute kAXMinValueAttribute
203 #define QAXMinimizeButtonAttribute kAXMinimizeButtonAttribute
204 #define QAXMinimizedAttribute kAXMinimizedAttribute
205 #define QAXNextContentsAttribute kAXNextContentsAttribute
206 #define QAXOrientationAttribute kAXOrientationAttribute
207 #define QAXParentAttribute kAXParentAttribute
208 #define QAXPickAction kAXPickAction
209 #define QAXPopUpButtonRole kAXPopUpButtonRole
210 #define QAXPositionAttribute kAXPositionAttribute
211 #define QAXPressAction kAXPressAction
212 #define QAXPreviousContentsAttribute kAXPreviousContentsAttribute
213 #define QAXProgressIndicatorRole kAXProgressIndicatorRole
214 #define QAXRadioButtonRole kAXRadioButtonRole
215 #define QAXRoleAttribute kAXRoleAttribute
216 #define QAXRoleDescriptionAttribute kAXRoleDescriptionAttribute
217 #define QAXRowRole kAXRowRole
218 #define QAXRowsAttribute kAXRowsAttribute
219 #define QAXScrollAreaRole kAXScrollAreaRole
220 #define QAXScrollBarRole kAXScrollBarRole
221 #define QAXSelectedAttribute kAXSelectedAttribute
222 #define QAXSelectedChildrenAttribute kAXSelectedChildrenAttribute
223 #define QAXSelectedRowsAttribute kAXSelectedRowsAttribute
224 #define QAXSizeAttribute kAXSizeAttribute
225 #define QAXSliderRole kAXSliderRole
226 #define QAXSplitGroupRole kAXSplitGroupRole
227 #define QAXSplitterRole kAXSplitterRole
228 #define QAXSplittersAttribute kAXSplittersAttribute
229 #define QAXStaticTextRole kAXStaticTextRole
230 #define QAXSubroleAttribute kAXSubroleAttribute
231 #define QAXTabGroupRole kAXTabGroupRole
232 #define QAXTableRole kAXTableRole
233 #define QAXTabsAttribute kAXTabsAttribute
234 #define QAXTextFieldRole kAXTextFieldRole
235 #define QAXTitleAttribute kAXTitleAttribute
236 #define QAXTitleUIElementAttribute kAXTitleUIElementAttribute
237 #define QAXToolbarButtonAttribute kAXToolbarButtonAttribute
238 #define QAXToolbarRole kAXToolbarRole
239 #define QAXTopLevelUIElementAttribute kAXTopLevelUIElementAttribute
240 #define QAXUnknownRole kAXUnknownRole
241 #define QAXValueAttribute kAXValueAttribute
242 #define QAXValueChangedNotification kAXValueChangedNotification
243 #define QAXValueIndicatorRole kAXValueIndicatorRole
244 #define QAXVerticalOrientationValue kAXVerticalOrientationValue
245 #define QAXVerticalScrollBarAttribute kAXVerticalScrollBarAttribute
246 #define QAXVisibleRowsAttribute kAXVisibleRowsAttribute
247 #define QAXWindowAttribute kAXWindowAttribute
248 #define QAXWindowCreatedNotification kAXWindowCreatedNotification
249 #define QAXWindowMovedNotification kAXWindowMovedNotification
250 #define QAXWindowRole kAXWindowRole
251 #define QAXZoomButtonAttribute kAXZoomButtonAttribute
252 #endif
253
254
255 /*****************************************************************************
256   Externals
257  *****************************************************************************/
258 extern bool qt_mac_is_macsheet(const QWidget *w); //qwidget_mac.cpp
259 extern bool qt_mac_is_macdrawer(const QWidget *w); //qwidget_mac.cpp
260
261 /*****************************************************************************
262   QAccessible Bindings
263  *****************************************************************************/
264 //hardcoded bindings between control info and (known) QWidgets
265 struct QAccessibleTextBinding {
266     int qt;
267     QAXRoleType mac;
268     bool settable;
269 } text_bindings[][10] = {
270     { { QAccessible::MenuItem, QAXMenuItemRole, false },
271       { -1, 0, false }
272     },
273     { { QAccessible::MenuBar, QAXMenuBarRole, false },
274       { -1, 0, false }
275     },
276     { { QAccessible::ScrollBar, QAXScrollBarRole, false },
277       { -1, 0, false }
278     },
279     { { QAccessible::Grip, QAXGrowAreaRole, false },
280       { -1, 0, false }
281     },
282     { { QAccessible::Window, QAXWindowRole, false },
283       { -1, 0, false }
284     },
285     { { QAccessible::Dialog, QAXWindowRole, false },
286       { -1, 0, false }
287     },
288     { { QAccessible::AlertMessage, QAXWindowRole, false },
289       { -1, 0, false }
290     },
291     { { QAccessible::ToolTip, QAXWindowRole, false },
292       { -1, 0, false }
293     },
294     { { QAccessible::HelpBalloon, QAXWindowRole, false },
295       { -1, 0, false }
296     },
297     { { QAccessible::PopupMenu, QAXMenuRole, false },
298       { -1, 0, false }
299     },
300     { { QAccessible::Application, QAXApplicationRole, false },
301       { -1, 0, false }
302     },
303     { { QAccessible::Pane, QAXGroupRole, false },
304       { -1, 0, false }
305     },
306     { { QAccessible::Grouping, QAXGroupRole, false },
307       { -1, 0, false }
308     },
309     { { QAccessible::Separator, QAXSplitterRole, false },
310       { -1, 0, false }
311     },
312     { { QAccessible::ToolBar, QAXToolbarRole, false },
313       { -1, 0, false }
314     },
315     { { QAccessible::PageTab, QAXRadioButtonRole, false },
316       { -1, 0, false }
317     },
318     { { QAccessible::ButtonMenu, QAXMenuButtonRole, false },
319       { -1, 0, false }
320     },
321     { { QAccessible::ButtonDropDown, QAXPopUpButtonRole, false },
322       { -1, 0, false }
323     },
324     { { QAccessible::SpinBox, QAXIncrementorRole, false },
325       { -1, 0, false }
326     },
327     { { QAccessible::Slider, QAXSliderRole, false },
328       { -1, 0, false }
329     },
330     { { QAccessible::ProgressBar, QAXProgressIndicatorRole, false },
331       { -1, 0, false }
332     },
333     { { QAccessible::ComboBox, QAXPopUpButtonRole, false },
334       { -1, 0, false }
335     },
336     { { QAccessible::RadioButton, QAXRadioButtonRole, false },
337       { -1, 0, false }
338     },
339     { { QAccessible::CheckBox, QAXCheckBoxRole, false },
340       { -1, 0, false }
341     },
342     { { QAccessible::StaticText, QAXStaticTextRole, false },
343       { QAccessible::Name, QAXValueAttribute, false },
344       { -1, 0, false }
345     },
346     { { QAccessible::Table, QAXTableRole, false },
347       { -1, 0, false }
348     },
349     { { QAccessible::StatusBar, QAXStaticTextRole, false },
350       { -1, 0, false }
351     },
352     { { QAccessible::Column, QAXColumnRole, false },
353       { -1, 0, false }
354     },
355     { { QAccessible::ColumnHeader, QAXColumnRole, false },
356       { -1, 0, false }
357     },
358     { { QAccessible::Row, QAXRowRole, false },
359       { -1, 0, false }
360     },
361     { { QAccessible::RowHeader, QAXRowRole, false },
362       { -1, 0, false }
363     },
364     { { QAccessible::Cell, QAXTextFieldRole, false },
365       { -1, 0, false }
366     },
367     { { QAccessible::PushButton, QAXButtonRole, false },
368       { -1, 0, false }
369     },
370     { { QAccessible::EditableText, QAXTextFieldRole, true },
371       { -1, 0, false }
372     },
373     { { QAccessible::Link, QAXTextFieldRole, false },
374       { -1, 0, false }
375     },
376     { { QAccessible::Indicator, QAXValueIndicatorRole, false },
377       { -1, 0, false }
378     },
379     { { QAccessible::Splitter, QAXSplitGroupRole, false },
380       { -1, 0, false }
381     },
382     { { QAccessible::List, QAXListRole, false },
383       { -1, 0, false }
384     },
385     { { QAccessible::ListItem, QAXStaticTextRole, false },
386       { -1, 0, false }
387     },
388     { { QAccessible::Cell, QAXStaticTextRole, false },
389       { -1, 0, false }
390     },
391     { { -1, 0, false } }
392 };
393
394 class QAInterface;
395 static CFStringRef macRole(const QAInterface &interface);
396
397 QDebug operator<<(QDebug debug, const QAInterface &interface)
398 {
399     if (interface.isValid() == false)
400         debug << "invalid interface";
401     else 
402         debug << interface.object() << "id" << interface.id() << "role" << hex << interface.role();
403     return debug;
404 }
405
406 // The root of the Qt accessible hiearchy.
407 static QObject *rootObject = 0;
408
409
410 bool QAInterface::operator==(const QAInterface &other) const
411 {
412     if (isValid() == false || other.isValid() == false)
413         return (isValid() && other.isValid());
414     
415     // walk up the parent chain, comparing child indexes, until we reach
416     // an interface that has a QObject.
417     QAInterface currentThis = *this;
418     QAInterface currentOther = other;
419     
420     while (currentThis.object() == 0) {
421         if (currentOther.object() != 0)
422             return false;
423
424         // fail if the child indexes in the two hirearchies don't match.
425         if (currentThis.parent().indexOfChild(currentThis) !=
426             currentOther.parent().indexOfChild(currentOther))
427             return false;
428
429         currentThis = currentThis.parent();
430         currentOther = currentOther.parent();
431     }
432     
433     return (currentThis.object() == currentOther.object() && currentThis.id() == currentOther.id());
434 }
435
436 bool QAInterface::operator!=(const QAInterface &other) const
437 {
438     return !operator==(other);
439 }
440
441 uint qHash(const QAInterface &item)
442 {
443     if (item.isValid())
444         return qHash(item.object()) + qHash(item.id());
445     else
446         return qHash(item.cachedObject()) + qHash(item.id());
447 }
448
449 QAInterface QAInterface::navigate(RelationFlag relation, int entry) const
450 {
451         if (!checkValid())
452             return QAInterface();
453
454     // On a QAccessibleInterface that handles its own children we can short-circut
455     // the navigation if this QAInterface refers to one of the children:
456     if (child != 0) {
457         // The Ancestor interface will always be the same QAccessibleInterface with
458         // a child value of 0.
459         if (relation == QAccessible::Ancestor)
460             return QAInterface(*this, 0);
461
462         // The child hiearchy is only one level deep, so navigating to a child
463         // of a child is not possible.
464         if (relation == QAccessible::Child) {
465             return QAInterface();
466         }
467     }
468     QAccessibleInterface *child_iface = 0;
469
470     const int status = base.interface->navigate(relation, entry, &child_iface);
471
472     if (status == -1)
473         return QAInterface(); // not found;
474
475     // Check if target is a child of this interface.
476     if (!child_iface) {
477         return QAInterface(*this, status);
478     } else {
479         // Target is child_iface or a child of that (status decides).
480         return QAInterface(child_iface, status);
481     }
482 }
483
484 QAElement::QAElement()
485 :elementRef(0)
486 {}
487
488 QAElement::QAElement(AXUIElementRef elementRef)
489 :elementRef(elementRef)
490 {
491     if (elementRef != 0) {
492         CFRetain(elementRef);
493         CFRetain(object());
494     }
495 }
496
497 QAElement::QAElement(const QAElement &element)
498 :elementRef(element.elementRef)
499 {
500     if (elementRef != 0) {
501         CFRetain(elementRef);
502         CFRetain(object());
503     }
504 }
505
506 QAElement::QAElement(HIObjectRef object, int child)
507 {
508 #ifndef QT_MAC_USE_COCOA
509     if (object == 0) {
510         elementRef = 0; // Create invalid QAElement.
511     } else {
512         elementRef = AXUIElementCreateWithHIObjectAndIdentifier(object, child);
513         CFRetain(object);
514     }
515 #else
516     Q_UNUSED(object);
517     Q_UNUSED(child);
518 #endif
519 }
520
521 QAElement::~QAElement()
522 {
523     if (elementRef != 0) {
524         CFRelease(object());
525         CFRelease(elementRef);
526     }
527 }
528
529 void QAElement::operator=(const QAElement &other)
530 {
531     if (*this == other)
532         return;
533
534     if (elementRef != 0) {
535         CFRelease(object());
536         CFRelease(elementRef);
537     }
538
539     elementRef = other.elementRef;
540
541     if (elementRef != 0) {
542         CFRetain(elementRef);
543         CFRetain(object());
544     }
545 }
546
547 bool QAElement::operator==(const QAElement &other) const
548 {
549     if (elementRef == 0 || other.elementRef == 0)
550         return (elementRef == other.elementRef);
551
552     return CFEqual(elementRef, other.elementRef);
553 }
554
555 uint qHash(QAElement element)
556 {
557     return qHash(element.object()) + qHash(element.id());
558 }
559
560 #ifndef QT_MAC_USE_COCOA
561 static QInterfaceFactory *createFactory(const QAInterface &interface);
562 #endif
563 Q_GLOBAL_STATIC(QAccessibleHierarchyManager, accessibleHierarchyManager);
564
565 /*
566     Reomves all accessibility info accosiated with the sender object.
567 */
568 void QAccessibleHierarchyManager::objectDestroyed(QObject *object)
569 {
570     HIObjectRef hiObject = qobjectHiobjectHash.value(object);
571     delete qobjectElementHash.value(object);
572     qobjectElementHash.remove(object);
573     hiobjectInterfaceHash.remove(hiObject);
574 }
575
576 /*
577     Removes all stored items.
578 */
579 void QAccessibleHierarchyManager::reset()
580 {
581     qDeleteAll(qobjectElementHash);
582     qobjectElementHash.clear();
583     hiobjectInterfaceHash.clear();
584     qobjectHiobjectHash.clear();
585 }
586
587 QAccessibleHierarchyManager *QAccessibleHierarchyManager::instance()
588 {
589     return accessibleHierarchyManager();
590 }
591
592 #ifndef QT_MAC_USE_COCOA
593 static bool isItemView(const QAInterface &interface)
594 {
595     QObject *object = interface.object();
596     return (interface.role() == QAccessible::List || interface.role() == QAccessible::Table
597             || (object && qobject_cast<QAbstractItemView *>(interface.object()))
598             || (object && object->objectName() == QLatin1String("qt_scrollarea_viewport")
599                 && qobject_cast<QAbstractItemView *>(object->parent())));
600 }
601 #endif
602
603 static bool isTabWidget(const QAInterface &interface)
604 {
605     if (QObject *object = interface.object())
606         return (object->inherits("QTabWidget") && interface.id() == 0);
607     return false;
608 }
609
610 static bool isStandaloneTabBar(const QAInterface &interface)
611 {
612     QObject *object = interface.object();
613     if (interface.role() == QAccessible::PageTabList && object)
614         return (qobject_cast<QTabWidget *>(object->parent()) == 0);
615
616     return false;
617 }
618
619 static bool isEmbeddedTabBar(const QAInterface &interface)
620 {
621     QObject *object = interface.object();
622     if (interface.role() == QAccessible::PageTabList && object)
623         return (qobject_cast<QTabWidget *>(object->parent()));
624
625     return false;
626 }
627
628 /*
629     Decides if a QAInterface is interesting from an accessibility users point of view.
630 */
631 bool isItInteresting(const QAInterface &interface)
632 {
633     // Mac accessibility does not have an attribute that corresponds to the Invisible/Offscreen
634     // state, so we disable the interface here.
635     const QAccessible::State state = interface.state();
636     if (state & QAccessible::Invisible ||
637         state & QAccessible::Offscreen )
638         return false;
639
640     const QAccessible::Role role = interface.role();
641
642     if (QObject * const object = interface.object()) {
643         const QString className = QLatin1String(object->metaObject()->className());
644
645         // VoiceOver focusing on tool tips can be confusing. The contents of the
646         // tool tip is avalible through the description attribute anyway, so
647         // we disable accessibility for tool tips.
648         if (className == QLatin1String("QTipLabel"))
649             return false;
650
651         // Hide TabBars that has a QTabWidget parent (the tab widget handles the accessibility)
652         if (isEmbeddedTabBar(interface))
653             return false;
654
655          // Hide docked dockwidgets. ### causes infinitie loop in the apple accessibility code.
656      /*    if (QDockWidget *dockWidget = qobject_cast<QDockWidget *>(object)) {
657             if (dockWidget->isFloating() == false)
658                 return false;        
659          }
660     */
661     }
662
663     // Client is a generic role returned by plain QWidgets or other
664     // widgets that does not have separate QAccessible interface, such
665     // as the TabWidget. Return false unless macRole gives the interface
666     // a special role.
667     if (role == QAccessible::Client && macRole(interface) == CFStringRef(QAXUnknownRole))
668         return false;
669
670     // Some roles are not interesting:
671     if (role == QAccessible::Border ||    // QFrame
672         role == QAccessible::Application || // We use the system-provided application element.
673         role == QAccessible::MenuItem)      // The system also provides the menu items.
674         return false;
675
676     // It is probably better to access the toolbar buttons directly than having
677     // to navigate through the toolbar.
678     if (role == QAccessible::ToolBar)
679         return false;
680
681     return true;
682 }
683
684 QAElement QAccessibleHierarchyManager::registerInterface(QObject *object, int child)
685 {
686 #ifndef QT_MAC_USE_COCOA
687     return registerInterface(QAInterface(QAccessible::queryAccessibleInterface(object), child));
688 #else
689     Q_UNUSED(object);
690     Q_UNUSED(child);
691     return QAElement();
692 #endif
693 }
694
695 /*
696     Creates a QAXUIelement that corresponds to the given QAInterface.
697 */
698 QAElement QAccessibleHierarchyManager::registerInterface(const QAInterface &interface)
699 {
700 #ifndef QT_MAC_USE_COCOA
701     if (interface.isValid() == false)
702         return QAElement();
703     QAInterface objectInterface = interface.objectInterface();
704
705     QObject * qobject = objectInterface.object();
706     HIObjectRef hiobject = objectInterface.hiObject();
707     if (qobject == 0 || hiobject == 0)
708         return QAElement();
709
710     if (qobjectElementHash.contains(qobject) == false) {
711         registerInterface(qobject, hiobject, createFactory(interface));
712         HIObjectSetAccessibilityIgnored(hiobject, !isItInteresting(interface));
713     }
714
715     return QAElement(hiobject, interface.id());
716 #else
717     Q_UNUSED(interface);
718     return QAElement();
719 #endif
720 }
721
722 #ifndef QT_MAC_USE_COCOA
723 #include "qaccessible_mac_carbon.cpp"
724 #endif
725
726 void QAccessibleHierarchyManager::registerInterface(QObject * qobject, HIObjectRef hiobject, QInterfaceFactory *interfaceFactory)
727 {
728 #ifndef QT_MAC_USE_COCOA
729     if (qobjectElementHash.contains(qobject) == false) {
730         qobjectElementHash.insert(qobject, interfaceFactory);
731         qobjectHiobjectHash.insert(qobject, hiobject);
732         connect(qobject, SIGNAL(destroyed(QObject *)), SLOT(objectDestroyed(QObject *)));
733     }
734
735     if (hiobjectInterfaceHash.contains(hiobject) == false) {
736         hiobjectInterfaceHash.insert(hiobject, interfaceFactory);
737         installAcessibilityEventHandler(hiobject);
738     }
739 #else
740     Q_UNUSED(qobject);
741     Q_UNUSED(hiobject);
742     Q_UNUSED(interfaceFactory);
743 #endif
744 }
745
746 void QAccessibleHierarchyManager::registerChildren(const QAInterface &interface)
747 {
748     QObject * const object = interface.object();
749     if (object == 0)
750         return;
751
752     QInterfaceFactory *interfaceFactory = qobjectElementHash.value(object);
753     
754     if (interfaceFactory == 0)
755         return;
756
757     interfaceFactory->registerChildren();
758 }
759
760 QAInterface QAccessibleHierarchyManager::lookup(const AXUIElementRef &element)
761 {
762      if (element == 0)
763         return QAInterface();
764 #ifndef QT_MAC_USE_COCOA
765     HIObjectRef hiObject = AXUIElementGetHIObject(element);
766
767     QInterfaceFactory *factory = hiobjectInterfaceHash.value(hiObject);
768     if (factory == 0) {
769         return QAInterface();
770     }
771
772     UInt64 id;
773     AXUIElementGetIdentifier(element, &id);
774     return factory->interface(id);
775 #else
776     return QAInterface();
777 #endif
778 }
779
780 QAInterface QAccessibleHierarchyManager::lookup(const QAElement &element)
781 {
782     return lookup(element.element());
783 }
784
785 QAElement QAccessibleHierarchyManager::lookup(const QAInterface &interface)
786 {
787     if (interface.isValid() == false)
788         return QAElement();
789
790     QInterfaceFactory *factory = qobjectElementHash.value(interface.objectInterface().object());
791     if (factory == 0)
792         return QAElement();
793
794     return factory->element(interface);
795 }
796
797 QAElement QAccessibleHierarchyManager::lookup(QObject * const object, int id)
798 {
799     QInterfaceFactory *factory = qobjectElementHash.value(object);
800     if (factory == 0)
801         return QAElement();
802
803     return factory->element(id);
804 }
805
806 /*
807     Standard interface mapping, return the stored interface
808     or HIObjectRef, and there is an one-to-one mapping between
809     the identifier and child.
810 */
811 class QStandardInterfaceFactory : public QInterfaceFactory
812 {
813 public:
814     QStandardInterfaceFactory(const QAInterface &interface)
815     : m_interface(interface), object(interface.hiObject())
816     {
817         CFRetain(object);
818     }
819     
820     ~QStandardInterfaceFactory()
821     {
822          CFRelease(object);
823     }
824
825     
826     QAInterface interface(UInt64 identifier)
827     {
828         const int child = identifier;
829         return QAInterface(m_interface, child);
830     }
831
832     QAElement element(int id)
833     {
834         return QAElement(object, id);
835     }
836
837     QAElement element(const QAInterface &interface)
838     {
839         if (interface.object() == 0)
840             return QAElement();
841         return QAElement(object, interface.id());
842     }
843
844     void registerChildren()
845     {
846         const int childCount = m_interface.childCount();
847         for (int i = 1; i <= childCount; ++i) {
848             accessibleHierarchyManager()->registerInterface(m_interface.navigate(QAccessible::Child, i));
849         }
850     }
851
852 private:
853     QAInterface m_interface;
854     HIObjectRef object;
855 };
856
857 /*
858     Interface mapping where that creates one HIObject for each interface child.
859 */
860 class QMultipleHIObjectFactory : public QInterfaceFactory
861 {
862 public:
863     QMultipleHIObjectFactory(const QAInterface &interface)
864     : m_interface(interface)
865     {  }
866     
867     ~QMultipleHIObjectFactory()
868     {
869         foreach (HIObjectRef object, objects) {
870             CFRelease(object);
871         }
872     }
873
874     QAInterface interface(UInt64 identifier)
875     {
876         const int child = identifier;
877         return QAInterface(m_interface, child);
878     }
879
880     QAElement element(int child)
881     {
882         if (child == 0)
883             return QAElement(m_interface.hiObject(), 0);
884         
885         if (child > objects.count())
886             return QAElement();
887
888         return QAElement(objects.at(child - 1), child);
889     }
890
891     void registerChildren()
892     {
893 #ifndef QT_MAC_USE_COCOA
894         const int childCount = m_interface.childCount();
895         for (int i = 1; i <= childCount; ++i) {
896             HIObjectRef hiobject;
897             HIObjectCreate(kObjectQtAccessibility, 0, &hiobject);
898             objects.append(hiobject);
899               accessibleHierarchyManager()->registerInterface(m_interface.object(), hiobject, this);
900             HIObjectSetAccessibilityIgnored(hiobject, !isItInteresting(m_interface.navigate(QAccessible::Child, i)));
901         }
902 #endif
903     }
904
905 private:
906     QAInterface m_interface;
907     QList<HIObjectRef> objects;
908 };
909
910 class QItemViewInterfaceFactory : public QInterfaceFactory
911 {
912 public:
913     QItemViewInterfaceFactory(const QAInterface &interface)
914     : m_interface(interface), object(interface.hiObject())
915     {
916         CFRetain(object);
917         columnCount = 0;
918         if (QTableView * tableView = qobject_cast<QTableView *>(interface.parent().object())) {
919             if (tableView->model())
920                 columnCount = tableView->model()->columnCount();
921             if (tableView->verticalHeader())
922                 ++columnCount;
923         }
924     }
925     
926     ~QItemViewInterfaceFactory()
927     {
928         CFRelease(object);
929     }
930
931     QAInterface interface(UInt64 identifier)
932     {
933         if (identifier == 0)
934             return m_interface;
935
936         if (m_interface.role() == QAccessible::List)
937             return m_interface.childAt(identifier);
938         
939         if (m_interface.role() == QAccessible::Table) {
940             const int index = identifier;
941             if (index == 0)
942                 return m_interface; // return the item view interface.
943            
944             const int rowIndex = (index - 1) / (columnCount + 1);
945             const int cellIndex = (index - 1)  % (columnCount + 1);
946 /*
947             qDebug() << "index" << index;
948             qDebug() << "rowIndex" << rowIndex;
949             qDebug() << "cellIndex" << cellIndex;
950 */
951             const QAInterface rowInterface = m_interface.childAt(rowIndex + 1);
952
953             if ((cellIndex) == 0) // Is it a row?
954                 return rowInterface;
955             else {
956                 return rowInterface.childAt(cellIndex);
957             }
958         }
959
960         return QAInterface();
961     }
962
963     QAElement element(int id)
964     {
965         if (id != 0) {
966             return QAElement();
967         }
968         return QAElement(object, 0);
969     }
970
971     QAElement element(const QAInterface &interface)
972     {
973         if (interface.object() && interface.object() == m_interface.object()) {
974             return QAElement(object, 0);
975         } else if (m_interface.role() == QAccessible::List) {
976             if (interface.parent().object() && interface.parent().object() == m_interface.object())
977                 return QAElement(object, m_interface.indexOfChild(interface));
978         } else if (m_interface.role() == QAccessible::Table) {
979             QAInterface currentInterface = interface;
980             int index = 0;
981
982             while (currentInterface.isValid() && currentInterface.object() == 0) {
983                 const QAInterface parentInterface = currentInterface.parent();
984 /*
985                 qDebug() << "current index" << index;
986                 qDebug() << "current interface" << interface;
987
988                 qDebug() << "parent interface" << parentInterface;
989                 qDebug() << "grandparent interface" << parentInterface.parent();
990                 qDebug() << "childCount" << interface.childCount();
991                 qDebug() << "index of child" << parentInterface.indexOfChild(currentInterface);
992 */
993                 index += ((parentInterface.indexOfChild(currentInterface) - 1) * (currentInterface.childCount() + 1)) + 1;
994                 currentInterface = parentInterface;
995 //                qDebug() << "new current interface" << currentInterface;
996             }
997             if (currentInterface.object() == m_interface.object())
998                 return QAElement(object, index);
999
1000
1001         }
1002         return QAElement();
1003     }
1004
1005     void registerChildren()
1006     {
1007         // Item view child interfraces don't have their own qobjects, so there is nothing to register here.
1008     }
1009
1010 private:
1011     QAInterface m_interface;
1012     HIObjectRef object;
1013     int columnCount; // for table views;
1014 };
1015
1016 #ifndef QT_MAC_USE_COCOA
1017 static bool managesChildren(const QAInterface &interface)
1018 {
1019     return (interface.childCount() > 0 && interface.childAt(1).id() > 0);
1020 }
1021
1022 static QInterfaceFactory *createFactory(const QAInterface &interface)
1023 {
1024     if (isItemView(interface)) {
1025         return new QItemViewInterfaceFactory(interface);
1026     }  if (managesChildren(interface)) {
1027         return new QMultipleHIObjectFactory(interface);
1028     }
1029
1030     return new QStandardInterfaceFactory(interface);
1031 }
1032 #endif
1033
1034 QList<QAElement> lookup(const QList<QAInterface> &interfaces)
1035 {
1036     QList<QAElement> elements;
1037     foreach (const QAInterface &interface, interfaces)
1038         if (interface.isValid()) {
1039             const QAElement element = accessibleHierarchyManager()->lookup(interface);
1040             if (element.isValid())
1041                 elements.append(element);
1042         }
1043     return elements;
1044 }
1045
1046 // Debug output helpers:
1047 /*
1048 static QString nameForEventKind(UInt32 kind)
1049 {
1050     switch(kind) {
1051         case kEventAccessibleGetChildAtPoint:       return QString("GetChildAtPoint");      break;
1052         case kEventAccessibleGetAllAttributeNames:  return QString("GetAllAttributeNames"); break;
1053         case kEventAccessibleGetNamedAttribute:     return QString("GetNamedAttribute");    break;
1054         case kEventAccessibleSetNamedAttribute:     return QString("SetNamedAttribute");    break;
1055         case kEventAccessibleGetAllActionNames:     return QString("GetAllActionNames");    break;
1056         case kEventAccessibleGetFocusedChild:       return QString("GetFocusedChild");      break;
1057         default:
1058             return QString("Unknown accessibility event type: %1").arg(kind);
1059         break;
1060     };
1061 }
1062 */
1063 #ifndef QT_MAC_USE_COCOA
1064 static bool qt_mac_append_cf_uniq(CFMutableArrayRef array, CFTypeRef value)
1065 {
1066     if (value == 0)
1067         return false; 
1068
1069     CFRange range;
1070     range.location = 0;
1071     range.length = CFArrayGetCount(array);
1072     if(!CFArrayContainsValue(array, range, value)) {
1073         CFArrayAppendValue(array, value);
1074         return true;
1075     }
1076     return false;
1077 }
1078
1079 static OSStatus setAttributeValue(EventRef event, const QList<QAElement> &elements)
1080 {
1081     CFMutableArrayRef array = CFArrayCreateMutable(0, 0, &kCFTypeArrayCallBacks);
1082     foreach (const QAElement &element, elements) {
1083         if (element.isValid())
1084             CFArrayAppendValue(array, element.element());
1085     }
1086
1087     const OSStatus err = SetEventParameter(event, kEventParamAccessibleAttributeValue, 
1088                                            typeCFTypeRef, sizeof(array), &array);
1089     CFRelease(array);
1090     return err;
1091 }
1092 #endif //QT_MAC_USE_COCOA
1093
1094 /*
1095     Gets the AccessibleObject parameter from an event.
1096 */
1097 static inline AXUIElementRef getAccessibleObjectParameter(EventRef event)
1098 {
1099     AXUIElementRef element;
1100     GetEventParameter(event, kEventParamAccessibleObject, typeCFTypeRef, 0,
1101                         sizeof(element), 0, &element);
1102     return element;
1103 }
1104
1105 /*
1106     The application event handler makes sure that all top-level qt windows are registered
1107     before any accessibility events are handeled.
1108 */
1109 #ifndef QT_MAC_USE_COCOA
1110 static OSStatus applicationEventHandler(EventHandlerCallRef next_ref, EventRef event, void *)
1111 {
1112     QAInterface rootInterface(QAccessible::queryAccessibleInterface(rootObject ? rootObject : qApp), 0);
1113     accessibleHierarchyManager()->registerChildren(rootInterface);
1114
1115     return CallNextEventHandler(next_ref, event);
1116 }
1117
1118 /*
1119     Returns the value for element by combining the QAccessibility::Checked and
1120     QAccessibility::Mixed flags into an int value that the Mac accessibilty
1121     system understands. This works for check boxes, radio buttons, and the like.
1122     The return values are:
1123     0: unchecked
1124     1: checked
1125     2: undecided
1126 */
1127 static int buttonValue(QAInterface element)
1128 {
1129     const QAccessible::State state = element.state();
1130     if (state & QAccessible::Mixed)
1131         return 2;
1132     else if(state & QAccessible::Checked)
1133         return 1;
1134     else
1135         return 0;
1136 }
1137
1138 static QString getValue(const QAInterface &interface)
1139 {
1140     const QAccessible::Role role = interface.role();
1141     if (role == QAccessible::RadioButton || role == QAccessible::CheckBox)
1142         return QString::number(buttonValue(interface));
1143     else
1144         return interface.text(QAccessible::Value);
1145 }
1146 #endif //QT_MAC_USE_COCOA
1147
1148 /*
1149     Translates a QAccessible::Role into a mac accessibility role.
1150 */
1151 static CFStringRef macRole(const QAInterface &interface)
1152 {
1153     const QAccessible::Role qtRole = interface.role();
1154
1155 //    qDebug() << "role for" << interface.object() << "interface role" << hex << qtRole;
1156
1157     // Qt accessibility:  QAccessible::Splitter contains QAccessible::Grip.
1158     // Mac accessibility: AXSplitGroup contains AXSplitter.
1159     if (qtRole == QAccessible::Grip) {
1160         const QAInterface parent = interface.parent();
1161         if (parent.isValid() && parent.role() == QAccessible::Splitter)
1162             return CFStringRef(QAXSplitterRole);
1163     }
1164
1165     // Tab widgets and standalone tab bars get the kAXTabGroupRole. Accessibility
1166     // for tab bars emebedded in a tab widget is handled by the tab widget.
1167     if (isTabWidget(interface) || isStandaloneTabBar(interface))
1168         return kAXTabGroupRole;
1169
1170     if (QObject *object = interface.object()) {
1171         // ### The interface for an abstract scroll area returns the generic "Client"
1172         // role, so we have to to an extra detect on the QObject here.
1173         if (object->inherits("QAbstractScrollArea") && interface.id() == 0)
1174             return CFStringRef(QAXScrollAreaRole);
1175
1176         if (object->inherits("QDockWidget"))
1177             return CFStringRef(QAXUnknownRole);
1178     }
1179
1180     int i = 0;
1181     int testRole = text_bindings[i][0].qt;
1182     while (testRole != -1) {
1183         if (testRole == qtRole)
1184             return CFStringRef(text_bindings[i][0].mac);
1185         ++i;
1186         testRole = text_bindings[i][0].qt;
1187     }
1188
1189 //    qDebug() << "got unknown role!" << interface << interface.parent();
1190
1191     return CFStringRef(QAXUnknownRole);
1192 }
1193
1194 /*
1195     Translates a QAccessible::Role and an attribute name into a QAccessible::Text, taking into
1196     account execptions listed in text_bindings.
1197 */
1198 #ifndef QT_MAC_USE_COCOA
1199 static int textForRoleAndAttribute(QAccessible::Role role, CFStringRef attribute)
1200 {
1201      // Search for exception, return it if found.
1202     int testRole = text_bindings[0][0].qt;
1203     int i = 0;
1204     while (testRole != -1) {
1205         if (testRole == role) {
1206             int j = 1;
1207             int qtRole = text_bindings[i][j].qt;
1208             CFStringRef testAttribute = CFStringRef(text_bindings[i][j].mac);
1209             while (qtRole != -1) {
1210                 if (CFStringCompare(attribute, testAttribute, 0) == kCFCompareEqualTo) {
1211                     return (QAccessible::Text)qtRole;
1212                 }
1213                 ++j;
1214                 testAttribute = CFStringRef(text_bindings[i][j].mac); /// ### custom compare
1215                 qtRole = text_bindings[i][j].qt; /// ### custom compare
1216             }
1217             break;
1218         }
1219         ++i;
1220         testRole = text_bindings[i][0].qt;
1221     }
1222
1223     // Return default mappping
1224     if (CFStringCompare(attribute, CFStringRef(QAXTitleAttribute), 0) == kCFCompareEqualTo)
1225         return QAccessible::Name;
1226     else if (CFStringCompare(attribute, CFStringRef(QAXValueAttribute), 0) == kCFCompareEqualTo)
1227         return QAccessible::Value;
1228     else if (CFStringCompare(attribute, CFStringRef(QAXHelpAttribute), 0) == kCFCompareEqualTo)
1229         return QAccessible::Help;
1230     else if (CFStringCompare(attribute, CFStringRef(QAXDescriptionAttribute), 0) == kCFCompareEqualTo)
1231         return QAccessible::Description;
1232     else
1233         return -1;
1234 }
1235
1236 /*
1237     Returns the subrole string constant for the interface if it has one,
1238     else returns an empty string.
1239 */
1240 static QCFString subrole(const QAInterface &interface)
1241 {
1242     const QAInterface parent = interface.parent();
1243     if (parent.isValid() == false)
1244         return QCFString();
1245
1246     if (parent.role() == QAccessible::ScrollBar) {
1247         QCFString subrole;
1248         switch(interface.id()) {
1249             case 1: subrole = CFStringRef(QAXDecrementArrowSubrole); break;
1250             case 2: subrole = CFStringRef(QAXDecrementPageSubrole); break;
1251             case 4: subrole = CFStringRef(QAXIncrementPageSubrole); break;
1252             case 5: subrole = CFStringRef(QAXIncrementArrowSubrole); break;
1253             default:
1254             break;
1255         }
1256         return subrole;
1257     }
1258     return QCFString();
1259 }
1260
1261 // Gets the scroll bar orientation by asking the QAbstractSlider object directly.
1262 static Qt::Orientation scrollBarOrientation(const QAInterface &scrollBar)
1263 {
1264     QObject *const object = scrollBar.object();
1265     if (QAbstractSlider * const sliderObject = qobject_cast<QAbstractSlider * const>(object))
1266         return sliderObject->orientation();
1267
1268     return Qt::Vertical; // D'oh! The interface wasn't a scroll bar.
1269 }
1270
1271 static QAInterface scrollAreaGetScrollBarInterface(const QAInterface &scrollArea, Qt::Orientation orientation)
1272 {
1273     if (macRole(scrollArea) != CFStringRef(CFStringRef(QAXScrollAreaRole)))
1274         return QAInterface();
1275
1276     // Child 1 is the contents widget, 2 and 3 are the scroll bar containers wich contains possible scroll bars.
1277     for (int i = 2; i <= 3; ++i) {
1278         QAInterface scrollBarContainer = scrollArea.childAt(i);
1279         for (int i = 1; i <= scrollBarContainer.childCount(); ++i) {
1280             QAInterface scrollBar = scrollBarContainer.childAt(i);
1281             if (scrollBar.isValid() &&
1282                 scrollBar.role() == QAccessible::ScrollBar &&
1283                 scrollBarOrientation(scrollBar) == orientation)
1284                 return scrollBar;
1285         }
1286     }
1287
1288     return QAInterface();
1289 }
1290
1291 static bool scrollAreaHasScrollBar(const QAInterface &scrollArea, Qt::Orientation orientation)
1292 {
1293     return scrollAreaGetScrollBarInterface(scrollArea, orientation).isValid();
1294 }
1295
1296 static QAElement scrollAreaGetScrollBar(const QAInterface &scrollArea, Qt::Orientation orientation)
1297 {
1298     return accessibleHierarchyManager()->lookup(scrollAreaGetScrollBarInterface(scrollArea, orientation));
1299 }
1300
1301 static QAElement scrollAreaGetContents(const QAInterface &scrollArea)
1302 {
1303     // Child 1 is the contents widget,
1304     return accessibleHierarchyManager()->lookup(scrollArea.navigate(QAccessible::Child, 1));
1305 }
1306
1307 static QAElement tabWidgetGetContents(const QAInterface &interface)
1308 {
1309     // A kAXTabGroup has a kAXContents attribute, which consists of the
1310     // ui elements for the current tab page. Get the current tab page
1311     // from the QStackedWidget, where the current visible page can
1312     // be found at index 1.
1313     QAInterface stackedWidget = interface.childAt(1);
1314     accessibleHierarchyManager()->registerChildren(stackedWidget);
1315     QAInterface tabPageInterface = stackedWidget.childAt(1);
1316     return accessibleHierarchyManager()->lookup(tabPageInterface);
1317 }
1318
1319 static QList<QAElement> tabBarGetTabs(const QAInterface &interface)
1320 {
1321     // Get the tabs by searching for children with the "PageTab" role.
1322     // This filters out the left/right navigation buttons.
1323     accessibleHierarchyManager()->registerChildren(interface);
1324     QList<QAElement> tabs;
1325     const int numChildren = interface.childCount();
1326     for (int i = 1; i < numChildren + 1; ++i) {
1327         QAInterface child = interface.navigate(QAccessible::Child, i);
1328         if (child.isValid() && child.role() == QAccessible::PageTab) {
1329             tabs.append(accessibleHierarchyManager()->lookup(child));
1330         }
1331     }
1332     return tabs;
1333 }
1334
1335 static QList<QAElement> tabWidgetGetTabs(const QAInterface &interface)
1336 {
1337     // Each QTabWidget has two children, a QStackedWidget and a QTabBar.
1338     // Get the tabs from the QTabBar.
1339     return tabBarGetTabs(interface.childAt(2));
1340 }
1341
1342 static QList<QAElement> tabWidgetGetChildren(const QAInterface &interface)
1343 {
1344     // The children for a kAXTabGroup should consist of the tabs and the
1345     // contents of the current open tab page.
1346     QList<QAElement> children = tabWidgetGetTabs(interface);
1347     children += tabWidgetGetContents(interface);
1348     return children;
1349 }
1350 #endif //QT_MAC_USE_COCOA
1351
1352 /*
1353     Returns the label (buddy) interface for interface, or 0 if it has none.
1354 */
1355 /*
1356 static QAInterface findLabel(const QAInterface &interface)
1357 {
1358     return interface.navigate(QAccessible::Label, 1);
1359 }
1360 */
1361 /*
1362     Returns a list of interfaces this interface labels, or an empty list if it doesn't label any.
1363 */
1364 /*
1365 static QList<QAInterface> findLabelled(const QAInterface &interface)
1366 {
1367     QList<QAInterface> interfaceList;
1368
1369     int count = 1;
1370     const QAInterface labelled = interface.navigate(QAccessible::Labelled, count);
1371     while (labelled.isValid()) {
1372         interfaceList.append(labelled);
1373         ++count;
1374     }
1375     return interfaceList;
1376 }
1377 */
1378 /*
1379     Tests if the given QAInterface has data for a mac attribute.
1380 */
1381 #ifndef QT_MAC_USE_COCOA
1382 static bool supportsAttribute(CFStringRef attribute, const QAInterface &interface)
1383 {
1384     const int text = textForRoleAndAttribute(interface.role(), attribute);
1385
1386     // Special case: Static texts don't have a title.
1387     if (interface.role() == QAccessible::StaticText && attribute == CFStringRef(QAXTitleAttribute))
1388         return false;
1389
1390     // Return true if we the attribute matched a QAccessible::Role and we get text for that role from the interface.
1391     if (text != -1) {
1392         if (text == QAccessible::Value) // Special case for Value, see getValue()
1393             return !getValue(interface).isEmpty();
1394         else
1395             return !interface.text((QAccessible::Text)text).isEmpty();
1396     }
1397
1398     if (CFStringCompare(attribute, CFStringRef(QAXChildrenAttribute),  0) == kCFCompareEqualTo) {
1399         if (interface.childCount() > 0)
1400             return true;
1401     }
1402
1403     if (CFStringCompare(attribute, CFStringRef(QAXSubroleAttribute),  0) == kCFCompareEqualTo) {
1404         return (subrole(interface) != QCFString());
1405     }
1406
1407     return false;
1408 }
1409
1410 static void appendIfSupported(CFMutableArrayRef array, CFStringRef attribute, const QAInterface &interface)
1411 {
1412     if (supportsAttribute(attribute, interface))
1413         qt_mac_append_cf_uniq(array, attribute);
1414 }
1415
1416 /*
1417     Returns the names of the attributes the give QAInterface supports.
1418 */
1419 static OSStatus getAllAttributeNames(EventRef event, const QAInterface &interface, EventHandlerCallRef next_ref)
1420 {
1421     // Call system event handler.
1422     OSStatus err = CallNextEventHandler(next_ref, event);
1423     if(err != noErr && err != eventNotHandledErr)
1424         return err;
1425     CFMutableArrayRef attrs = 0;
1426     GetEventParameter(event, kEventParamAccessibleAttributeNames, typeCFMutableArrayRef, 0,
1427                       sizeof(attrs), 0, &attrs);
1428
1429     if (!attrs)
1430         return eventNotHandledErr;
1431
1432     // Append attribute names that are always supported.
1433     qt_mac_append_cf_uniq(attrs, CFStringRef(QAXPositionAttribute));
1434     qt_mac_append_cf_uniq(attrs, CFStringRef(QAXSizeAttribute));
1435     qt_mac_append_cf_uniq(attrs, CFStringRef(QAXRoleAttribute));
1436     qt_mac_append_cf_uniq(attrs, CFStringRef(QAXEnabledAttribute));
1437     qt_mac_append_cf_uniq(attrs, CFStringRef(QAXWindowAttribute));
1438     qt_mac_append_cf_uniq(attrs, CFStringRef(QAXTopLevelUIElementAttribute));
1439
1440     // Append these names if the QInterafceItem returns any data for them.
1441     appendIfSupported(attrs, CFStringRef(QAXTitleAttribute), interface);
1442     appendIfSupported(attrs, CFStringRef(QAXValueAttribute), interface);
1443     appendIfSupported(attrs, CFStringRef(QAXDescriptionAttribute), interface);
1444     appendIfSupported(attrs, CFStringRef(QAXLinkedUIElementsAttribute), interface);
1445     appendIfSupported(attrs, CFStringRef(QAXHelpAttribute), interface);
1446     appendIfSupported(attrs, CFStringRef(QAXTitleUIElementAttribute), interface);
1447     appendIfSupported(attrs, CFStringRef(QAXChildrenAttribute), interface);
1448     appendIfSupported(attrs, CFStringRef(QAXSubroleAttribute), interface);
1449
1450     // Append attribute names based on the interaface role.
1451     switch (interface.role())  {
1452         case QAccessible::Window:
1453             qt_mac_append_cf_uniq(attrs, CFStringRef(QAXMainAttribute));
1454             qt_mac_append_cf_uniq(attrs, CFStringRef(QAXMinimizedAttribute));
1455             qt_mac_append_cf_uniq(attrs, CFStringRef(QAXCloseButtonAttribute));
1456             qt_mac_append_cf_uniq(attrs, CFStringRef(QAXZoomButtonAttribute));
1457             qt_mac_append_cf_uniq(attrs, CFStringRef(QAXMinimizeButtonAttribute));
1458             qt_mac_append_cf_uniq(attrs, CFStringRef(QAXToolbarButtonAttribute));
1459             qt_mac_append_cf_uniq(attrs, CFStringRef(QAXGrowAreaAttribute));
1460         break;
1461         case QAccessible::RadioButton:
1462         case QAccessible::CheckBox:
1463             qt_mac_append_cf_uniq(attrs, CFStringRef(QAXMinValueAttribute));
1464             qt_mac_append_cf_uniq(attrs, CFStringRef(QAXMaxValueAttribute));
1465         break;
1466         case QAccessible::ScrollBar:
1467             qt_mac_append_cf_uniq(attrs, CFStringRef(QAXOrientationAttribute));
1468         break;
1469         case QAccessible::Splitter:
1470             qt_mac_append_cf_uniq(attrs, CFStringRef(QAXSplittersAttribute));
1471         break;
1472         case QAccessible::Table:
1473             qt_mac_append_cf_uniq(attrs, CFStringRef(QAXRowsAttribute));
1474             qt_mac_append_cf_uniq(attrs, CFStringRef(QAXVisibleRowsAttribute));
1475             qt_mac_append_cf_uniq(attrs, CFStringRef(QAXSelectedRowsAttribute));
1476         break;
1477         default:
1478         break;
1479     }
1480
1481     // Append attribute names based on the mac accessibility role.
1482     const QCFString mac_role = macRole(interface);
1483     if (mac_role == CFStringRef(QAXSplitterRole)) {
1484         qt_mac_append_cf_uniq(attrs, CFStringRef(QAXPreviousContentsAttribute));
1485         qt_mac_append_cf_uniq(attrs, CFStringRef(QAXNextContentsAttribute));
1486         qt_mac_append_cf_uniq(attrs, CFStringRef(QAXOrientationAttribute));
1487     } else if (mac_role == CFStringRef(QAXScrollAreaRole)) {
1488         if (scrollAreaHasScrollBar(interface, Qt::Horizontal))
1489             qt_mac_append_cf_uniq(attrs, CFStringRef(QAXHorizontalScrollBarAttribute));
1490         if (scrollAreaHasScrollBar(interface, Qt::Vertical))
1491             qt_mac_append_cf_uniq(attrs, CFStringRef(QAXVerticalScrollBarAttribute));
1492         qt_mac_append_cf_uniq(attrs, CFStringRef(QAXContentsAttribute));
1493     } else if (mac_role == CFStringRef(QAXTabGroupRole)) {
1494         qt_mac_append_cf_uniq(attrs, CFStringRef(QAXTabsAttribute));
1495         // Only tab widgets can have the contents attribute, there is no way of getting
1496         // the contents from a QTabBar.
1497         if (isTabWidget(interface)) 
1498             qt_mac_append_cf_uniq(attrs, CFStringRef(QAXContentsAttribute));
1499     }
1500
1501     return noErr;
1502 }
1503
1504 static void handleStringAttribute(EventRef event, QAccessible::Text text, const QAInterface &interface)
1505 {
1506     QString str = interface.text(text);
1507     if (str.isEmpty())
1508         return;
1509
1510     // Remove any html markup from the text string, or VoiceOver will read the html tags.
1511     static QTextDocument document;
1512     document.setHtml(str);
1513     str = document.toPlainText();
1514
1515     CFStringRef cfstr = QCFString::toCFStringRef(str);
1516     SetEventParameter(event, kEventParamAccessibleAttributeValue, typeCFStringRef, sizeof(cfstr), &cfstr);
1517 }
1518
1519 /*
1520     Handles the parent attribute for a interface.
1521     There are basically three cases here:
1522     1. interface is a HIView and has only HIView children.
1523     2. interface is a HIView but has children that is not a HIView
1524     3. interface is not a HIView.
1525 */
1526 static OSStatus handleChildrenAttribute(EventHandlerCallRef next_ref, EventRef event, QAInterface &interface)
1527 {
1528    // Add the children for this interface to the global QAccessibelHierachyManager.
1529     accessibleHierarchyManager()->registerChildren(interface);
1530
1531     if (isTabWidget(interface)) {
1532         QList<QAElement> children = tabWidgetGetChildren(interface);
1533         const int childCount = children.count();
1534
1535         CFMutableArrayRef array = 0;
1536         array = CFArrayCreateMutable(0, 0, &kCFTypeArrayCallBacks);
1537         for (int i = 0; i < childCount; ++i)  {
1538             qt_mac_append_cf_uniq(array, children.at(i).element());
1539         }
1540
1541         OSStatus err;
1542         err = SetEventParameter(event, kEventParamAccessibleAttributeValue, typeCFArrayRef, sizeof(array), &array);
1543         if (err != noErr)
1544             qWarning("Qt:Internal error (%s:%d)", __FILE__, __LINE__);
1545
1546         return noErr;
1547     }
1548
1549     const QList<QAElement> children = lookup(interface.children());
1550     const int childCount = children.count();
1551
1552     OSStatus err = eventNotHandledErr;
1553     if (interface.isHIView())
1554         err = CallNextEventHandler(next_ref, event);
1555
1556     CFMutableArrayRef array = 0;
1557     int arraySize = 0;
1558     if (err == noErr) {
1559         CFTypeRef obj = 0;
1560         err = GetEventParameter(event, kEventParamAccessibleAttributeValue, typeCFTypeRef, NULL , sizeof(obj), NULL, &obj);
1561         if (err == noErr && obj != 0) {
1562             array = (CFMutableArrayRef)obj;
1563             arraySize = CFArrayGetCount(array);
1564         }
1565     }
1566
1567     if (array) {
1568         CFArrayRemoveAllValues(array);
1569         for (int i = 0; i < childCount; ++i)  {
1570             qt_mac_append_cf_uniq(array, children.at(i).element());
1571         }
1572     } else {
1573         array = CFArrayCreateMutable(0, 0, &kCFTypeArrayCallBacks);
1574         for (int i = 0; i < childCount; ++i)  {
1575             qt_mac_append_cf_uniq(array, children.at(i).element());
1576         }
1577
1578         err = SetEventParameter(event, kEventParamAccessibleAttributeValue, typeCFArrayRef, sizeof(array), &array);
1579         if (err != noErr)
1580             qWarning("Qt:Internal error (%s:%d)", __FILE__, __LINE__);
1581     }
1582
1583     return noErr;
1584 }
1585
1586 /*
1587
1588 */
1589 static OSStatus handleParentAttribute(EventHandlerCallRef next_ref, EventRef event, const QAInterface &interface)
1590 {
1591     OSStatus err = eventNotHandledErr;
1592     if (interface.isHIView()) {
1593          err = CallNextEventHandler(next_ref, event);
1594     }
1595     if (err == noErr)
1596         return err;
1597
1598     const QAInterface parentInterface  = interface.navigate(QAccessible::Ancestor, 1);
1599     const QAElement parentElement = accessibleHierarchyManager()->lookup(parentInterface);
1600
1601     if (parentElement.isValid() == false)
1602         return eventNotHandledErr;
1603
1604     AXUIElementRef elementRef = parentElement.element();
1605     SetEventParameter(event, kEventParamAccessibleAttributeValue, typeCFTypeRef, sizeof(elementRef), &elementRef);
1606     return noErr;
1607 }
1608 #endif
1609
1610 struct IsWindowTest
1611 {
1612     static inline bool test(const QAInterface &interface)
1613     {
1614         return (interface.role() == QAccessible::Window);
1615     }
1616 };
1617
1618 struct IsWindowAndNotDrawerOrSheetTest
1619 {
1620     static inline bool test(const QAInterface &interface)
1621     {
1622         QWidget * const widget = qobject_cast<QWidget*>(interface.object());
1623         return (interface.role() == QAccessible::Window &&
1624                 widget && widget->isWindow() &&
1625                 !qt_mac_is_macdrawer(widget) &&
1626                 !qt_mac_is_macsheet(widget));
1627     }
1628 };
1629
1630 /*
1631     Navigates up the iterfaces ancestor hierachy until a QAccessibleInterface that
1632     passes the Test is found. If we reach a interface that is a HIView we stop the
1633     search and call AXUIElementCopyAttributeValue.
1634 */
1635 template <typename TestType>
1636 OSStatus navigateAncestors(EventHandlerCallRef next_ref, EventRef event, const QAInterface &interface, CFStringRef attribute)
1637 {
1638     if (interface.isHIView())
1639         return CallNextEventHandler(next_ref, event);
1640
1641     QAInterface current = interface;
1642     QAElement element;
1643     while (current.isValid()) {
1644         if (TestType::test(interface)) {
1645             element = accessibleHierarchyManager()->lookup(current);
1646             break;
1647         }
1648
1649         // If we reach an InterfaceItem that is a HiView we can hand of the search to
1650         // the system event handler. This is the common case.
1651         if (current.isHIView()) {
1652             CFTypeRef value = 0;
1653             const QAElement currentElement = accessibleHierarchyManager()->lookup(current);
1654             AXError err = AXUIElementCopyAttributeValue(currentElement.element(), attribute, &value);
1655             AXUIElementRef newElement = (AXUIElementRef)value;
1656
1657             if (err == noErr)
1658                 element = QAElement(newElement);
1659
1660             if (newElement != 0)
1661                 CFRelease(newElement);
1662             break;
1663         }
1664
1665         QAInterface next = current.parent();
1666         if (next.isValid() == false)
1667             break;
1668         if (next == current)
1669             break;
1670         current = next;
1671     }
1672
1673     if (element.isValid() == false)
1674         return eventNotHandledErr;
1675
1676
1677     AXUIElementRef elementRef = element.element();
1678     SetEventParameter(event, kEventParamAccessibleAttributeValue, typeCFTypeRef,
1679                                       sizeof(elementRef), &elementRef);
1680     return noErr;
1681 }
1682
1683 /*
1684     Returns the top-level window for an interface, which is the closest ancestor interface that
1685     has the Window role, but is not a sheet or a drawer.
1686 */
1687 #ifndef QT_MAC_USE_COCOA
1688 static OSStatus handleWindowAttribute(EventHandlerCallRef next_ref, EventRef event, const QAInterface &interface)
1689 {
1690     return navigateAncestors<IsWindowAndNotDrawerOrSheetTest>(next_ref, event, interface, CFStringRef(QAXWindowAttribute));
1691 }
1692
1693 /*
1694     Returns the top-level window for an interface, which is the closest ancestor interface that
1695     has the Window role. (Can also be a sheet or a drawer)
1696 */
1697 static OSStatus handleTopLevelUIElementAttribute(EventHandlerCallRef next_ref, EventRef event, const QAInterface &interface)
1698 {
1699     return navigateAncestors<IsWindowTest>(next_ref, event, interface, CFStringRef(QAXTopLevelUIElementAttribute));
1700 }
1701
1702 /*
1703     Returns the tab buttons for an interface.
1704 */
1705 static OSStatus handleTabsAttribute(EventHandlerCallRef next_ref, EventRef event, QAInterface &interface)
1706 {
1707     Q_UNUSED(next_ref);
1708     if (isTabWidget(interface))
1709         return setAttributeValue(event, tabWidgetGetTabs(interface));
1710     else
1711         return setAttributeValue(event, tabBarGetTabs(interface));
1712 }
1713
1714 static OSStatus handlePositionAttribute(EventHandlerCallRef, EventRef event, const QAInterface &interface)
1715 {
1716     QPoint qpoint(interface.rect().topLeft());
1717     HIPoint point;
1718     point.x = qpoint.x();
1719     point.y = qpoint.y();
1720     SetEventParameter(event, kEventParamAccessibleAttributeValue, typeHIPoint, sizeof(point), &point);
1721     return noErr;
1722 }
1723
1724 static OSStatus handleSizeAttribute(EventHandlerCallRef, EventRef event, const QAInterface &interface)
1725 {
1726     QSize qSize(interface.rect().size());
1727     HISize size;
1728     size.width = qSize.width();
1729     size.height = qSize.height();
1730     SetEventParameter(event, kEventParamAccessibleAttributeValue, typeHISize, sizeof(size), &size);
1731     return noErr;
1732 }
1733
1734 static OSStatus handleSubroleAttribute(EventHandlerCallRef, EventRef event, const QAInterface &interface)
1735 {
1736     const QCFString role = subrole(interface);
1737     CFStringRef rolestr = (CFStringRef)role;
1738     SetEventParameter(event, kEventParamAccessibleAttributeValue, typeCFTypeRef, sizeof(rolestr), &rolestr);
1739     return noErr;
1740 }
1741
1742 static OSStatus handleOrientationAttribute(EventHandlerCallRef next_ref, EventRef event, const QAInterface &interface)
1743 {
1744     QObject *const object = interface.object();
1745     Qt::Orientation orientation;
1746     if (interface.role() == QAccessible::ScrollBar) {
1747         orientation  = scrollBarOrientation(interface);
1748     } else if (QSplitterHandle * const splitter = qobject_cast<QSplitterHandle * const>(object)) {
1749         // Qt reports the layout orientation, but we want the splitter handle orientation.
1750         orientation = (splitter->orientation() == Qt::Horizontal) ? Qt::Vertical : Qt::Horizontal;
1751     } else {
1752         return CallNextEventHandler(next_ref, event);
1753     }
1754     const CFStringRef orientationString = (orientation == Qt::Vertical)
1755         ? CFStringRef(QAXVerticalOrientationValue) : CFStringRef(QAXHorizontalOrientationValue);
1756     SetEventParameter(event, kEventParamAccessibleAttributeValue, typeCFStringRef, sizeof(orientationString), &orientationString);
1757     return noErr;
1758 }
1759
1760 /*
1761     Figures out the next or previous contents for a splitter.
1762 */
1763 static OSStatus handleSplitterContentsAttribute(EventHandlerCallRef next_ref, EventRef event, const QAInterface &interface, QCFString nextOrPrev)
1764 {
1765     if (interface.isValid() == false || interface.role() != QAccessible::Grip)
1766         return eventNotHandledErr;
1767
1768     const QAInterface parent = interface.parent();
1769     if (parent.isValid() == false)
1770         return CallNextEventHandler(next_ref, event);
1771
1772     if (parent.role() != QAccessible::Splitter)
1773         return CallNextEventHandler(next_ref, event);
1774
1775     const QSplitter * const splitter = qobject_cast<const QSplitter * const>(parent.object());
1776     if (splitter == 0)
1777         return CallNextEventHandler(next_ref, event);
1778
1779     QWidget * const splitterHandle = qobject_cast<QWidget * const>(interface.object());
1780     const int splitterHandleIndex = splitter->indexOf(splitterHandle);
1781     const int widgetIndex = (nextOrPrev == QCFString(CFStringRef(QAXPreviousContentsAttribute))) ? splitterHandleIndex - 1 : splitterHandleIndex;
1782     const QAElement contentsElement = accessibleHierarchyManager()->lookup(splitter->widget(widgetIndex), 0);
1783     return setAttributeValue(event, QList<QAElement>() << contentsElement);
1784 }
1785
1786 /*
1787     Creates a list of all splitter handles the splitter contains.
1788 */
1789 static OSStatus handleSplittersAttribute(EventHandlerCallRef next_ref, EventRef event, QAInterface &interface)
1790 {
1791     const QSplitter * const splitter = qobject_cast<const QSplitter * const>(interface.object());
1792     if (splitter == 0)
1793         return CallNextEventHandler(next_ref, event);
1794
1795     accessibleHierarchyManager()->registerChildren(interface);
1796
1797     QList<QAElement> handles;
1798     const int visibleSplitterCount = splitter->count() -1; // skip first handle, it's always invisible.
1799     for (int i = 0; i < visibleSplitterCount; ++i)
1800         handles.append(accessibleHierarchyManager()->lookup(splitter->handle(i + 1), 0));
1801
1802     return setAttributeValue(event, handles);
1803 }
1804
1805 // This handler gets the scroll bars for a scroll area
1806 static OSStatus handleScrollBarAttribute(EventHandlerCallRef next_ref, EventRef event, QAInterface &scrollArea, Qt::Orientation orientation)
1807 {
1808     QAElement scrollBar = scrollAreaGetScrollBar(scrollArea, orientation);
1809     if (scrollBar.isValid() == false)
1810         return CallNextEventHandler(next_ref, event);
1811
1812     AXUIElementRef elementRef = scrollBar.element();
1813     SetEventParameter(event, kEventParamAccessibleAttributeValue, typeCFTypeRef, sizeof(elementRef), &elementRef);
1814     return noErr;
1815 }
1816
1817 // This handler gets the contents for a scroll area or tab widget.
1818 static OSStatus handleContentsAttribute(EventHandlerCallRef next_ref, EventRef event, QAInterface &interface)
1819 {
1820     const QCFString mac_role = macRole(interface);
1821
1822     QAElement contents;
1823
1824     if (mac_role == kAXTabGroupRole) {
1825         contents = tabWidgetGetContents(interface);
1826     } else {
1827         contents = scrollAreaGetContents(interface);
1828         if (contents.isValid() == false)
1829             return CallNextEventHandler(next_ref, event);
1830     }
1831
1832     return setAttributeValue(event, QList<QAElement>() << contents);
1833 }
1834
1835 static OSStatus handleRowsAttribute(EventHandlerCallRef, EventRef event, QAInterface &tableView)
1836 {
1837     QList<QAElement> rows = lookup(tableView.children());
1838
1839     // kill the first row which is the horizontal header.
1840     rows.removeAt(0);
1841
1842     return setAttributeValue(event, rows);
1843 }
1844
1845 static OSStatus handleVisibleRowsAttribute(EventHandlerCallRef, EventRef event, QAInterface &tableView)
1846 {
1847     QList<QAElement> visibleRows;
1848
1849     QList<QAInterface> rows = tableView.children();
1850     // kill the first row which is the horizontal header.
1851     rows.removeAt(0);
1852
1853     foreach (const QAInterface &interface, rows)
1854         if ((interface.state() & QAccessible::Invisible) == false)
1855             visibleRows.append(accessibleHierarchyManager()->lookup(interface));
1856
1857     return setAttributeValue(event, visibleRows);
1858 }
1859
1860 static OSStatus handleSelectedRowsAttribute(EventHandlerCallRef, EventRef event, QAInterface &tableView)
1861 {
1862     QList<QAElement> selectedRows;
1863     foreach (const QAInterface &interface, tableView.children())
1864         if ((interface.state() & QAccessible::Selected))
1865             selectedRows.append(accessibleHierarchyManager()->lookup(interface));
1866
1867     return setAttributeValue(event, selectedRows);
1868 }
1869
1870 static OSStatus getNamedAttribute(EventHandlerCallRef next_ref, EventRef event, QAInterface &interface)
1871 {
1872     CFStringRef var;
1873     GetEventParameter(event, kEventParamAccessibleAttributeName, typeCFStringRef, 0,
1874                               sizeof(var), 0, &var);
1875
1876     if (CFStringCompare(var, CFStringRef(QAXChildrenAttribute), 0) == kCFCompareEqualTo) {
1877         return handleChildrenAttribute(next_ref, event, interface);
1878     } else if(CFStringCompare(var, CFStringRef(QAXTopLevelUIElementAttribute), 0) == kCFCompareEqualTo) {
1879         return handleTopLevelUIElementAttribute(next_ref, event, interface);
1880     } else if(CFStringCompare(var, CFStringRef(QAXWindowAttribute), 0) == kCFCompareEqualTo) {
1881         return handleWindowAttribute(next_ref, event, interface);
1882     } else if(CFStringCompare(var, CFStringRef(QAXParentAttribute), 0) == kCFCompareEqualTo) {
1883         return handleParentAttribute(next_ref, event, interface);
1884     } else if (CFStringCompare(var, CFStringRef(QAXPositionAttribute), 0) == kCFCompareEqualTo) {
1885         return handlePositionAttribute(next_ref, event, interface);
1886     } else if (CFStringCompare(var, CFStringRef(QAXSizeAttribute), 0) == kCFCompareEqualTo) {
1887         return handleSizeAttribute(next_ref, event, interface);
1888     } else  if (CFStringCompare(var, CFStringRef(QAXRoleAttribute), 0) == kCFCompareEqualTo) {
1889         CFStringRef role = macRole(interface);
1890 // ###
1891 //        QWidget * const widget = qobject_cast<QWidget *>(interface.object());
1892 //        if (role == CFStringRef(QAXUnknownRole) && widget && widget->isWindow())
1893 //            role = CFStringRef(QAXWindowRole);
1894
1895         SetEventParameter(event, kEventParamAccessibleAttributeValue, typeCFStringRef,
1896                           sizeof(role), &role);
1897
1898     } else if (CFStringCompare(var, CFStringRef(QAXEnabledAttribute), 0) == kCFCompareEqualTo) {
1899         Boolean val =  !((interface.state() & QAccessible::Unavailable))
1900                      && !((interface.state() & QAccessible::Invisible));
1901         SetEventParameter(event, kEventParamAccessibleAttributeValue, typeBoolean,
1902                           sizeof(val), &val);
1903     } else if (CFStringCompare(var, CFStringRef(QAXExpandedAttribute), 0) == kCFCompareEqualTo) {
1904         Boolean val = (interface.state() & QAccessible::Expanded);
1905         SetEventParameter(event, kEventParamAccessibleAttributeValue, typeBoolean,
1906                           sizeof(val), &val);
1907     } else if (CFStringCompare(var, CFStringRef(QAXSelectedAttribute), 0) == kCFCompareEqualTo) {
1908         Boolean val = (interface.state() & QAccessible::Selection);
1909         SetEventParameter(event, kEventParamAccessibleAttributeValue, typeBoolean,
1910                           sizeof(val), &val);
1911     } else if (CFStringCompare(var, CFStringRef(QAXFocusedAttribute), 0) == kCFCompareEqualTo) {
1912         Boolean val = (interface.state() & QAccessible::Focus);
1913         SetEventParameter(event, kEventParamAccessibleAttributeValue, typeBoolean,
1914                           sizeof(val), &val);
1915     } else if (CFStringCompare(var, CFStringRef(QAXSelectedChildrenAttribute), 0) == kCFCompareEqualTo) {
1916         const int cc = interface.childCount();
1917         QList<QAElement> selected;
1918         for (int i = 1; i <= cc; ++i) {
1919             const QAInterface child_iface = interface.navigate(QAccessible::Child, i);
1920             if (child_iface.isValid() && child_iface.state() & QAccessible::Selected)
1921                 selected.append(accessibleHierarchyManager()->lookup(child_iface));
1922         }
1923
1924         return setAttributeValue(event, selected);
1925
1926       } else if (CFStringCompare(var, CFStringRef(QAXCloseButtonAttribute), 0) == kCFCompareEqualTo) {
1927         if(interface.object() && interface.object()->isWidgetType()) {
1928             Boolean val = true; //do we want to add a WState for this?
1929             SetEventParameter(event, kEventParamAccessibleAttributeValue, typeBoolean,
1930                               sizeof(val), &val);
1931         }
1932     } else if (CFStringCompare(var, CFStringRef(QAXZoomButtonAttribute), 0) == kCFCompareEqualTo) {
1933         if(interface.object() && interface.object()->isWidgetType()) {
1934             QWidget *widget = (QWidget*)interface.object();
1935             Boolean val = (widget->windowFlags() & Qt::WindowMaximizeButtonHint);
1936             SetEventParameter(event, kEventParamAccessibleAttributeValue, typeBoolean,
1937                               sizeof(val), &val);
1938         }
1939     } else if (CFStringCompare(var, CFStringRef(QAXMinimizeButtonAttribute), 0) == kCFCompareEqualTo) {
1940         if(interface.object() && interface.object()->isWidgetType()) {
1941             QWidget *widget = (QWidget*)interface.object();
1942             Boolean val = (widget->windowFlags() & Qt::WindowMinimizeButtonHint);
1943             SetEventParameter(event, kEventParamAccessibleAttributeValue, typeBoolean,
1944                               sizeof(val), &val);
1945         }
1946     } else if (CFStringCompare(var, CFStringRef(QAXToolbarButtonAttribute), 0) == kCFCompareEqualTo) {
1947         if(interface.object() && interface.object()->isWidgetType()) {
1948             QWidget *widget = (QWidget*)interface.object();
1949             Boolean val = qobject_cast<QMainWindow *>(widget) != 0;
1950             SetEventParameter(event, kEventParamAccessibleAttributeValue, typeBoolean,
1951                               sizeof(val), &val);
1952         }
1953     } else if (CFStringCompare(var, CFStringRef(QAXGrowAreaAttribute), 0) == kCFCompareEqualTo) {
1954         if(interface.object() && interface.object()->isWidgetType()) {
1955             Boolean val = true; //do we want to add a WState for this?
1956             SetEventParameter(event, kEventParamAccessibleAttributeValue, typeBoolean,
1957                               sizeof(val), &val);
1958         }
1959     } else if (CFStringCompare(var, CFStringRef(QAXMinimizedAttribute), 0) == kCFCompareEqualTo) {
1960         if (interface.object() && interface.object()->isWidgetType()) {
1961             QWidget *widget = (QWidget*)interface.object();
1962             Boolean val = (widget->windowState() & Qt::WindowMinimized);
1963             SetEventParameter(event, kEventParamAccessibleAttributeValue, typeBoolean,
1964                               sizeof(val), &val);
1965         }
1966     } else if (CFStringCompare(var, CFStringRef(QAXSubroleAttribute), 0) == kCFCompareEqualTo) {
1967         return handleSubroleAttribute(next_ref, event, interface);
1968     } else if (CFStringCompare(var, CFStringRef(QAXRoleDescriptionAttribute), 0) == kCFCompareEqualTo) {
1969 #if !defined(QT_MAC_USE_COCOA)
1970         if (HICopyAccessibilityRoleDescription) {
1971             const CFStringRef roleDescription = HICopyAccessibilityRoleDescription(macRole(interface), 0);
1972             SetEventParameter(event, kEventParamAccessibleAttributeValue, typeCFStringRef,
1973                           sizeof(roleDescription), &roleDescription);
1974         } else
1975 #endif
1976         {
1977             // Just use Qt::Description on 10.3
1978             handleStringAttribute(event, QAccessible::Description, interface);
1979         }
1980     } else if (CFStringCompare(var, CFStringRef(QAXTitleAttribute), 0) == kCFCompareEqualTo) {
1981         const QAccessible::Role role = interface.role();
1982         const QAccessible::Text text = (QAccessible::Text)textForRoleAndAttribute(role, var);
1983         handleStringAttribute(event, text, interface);
1984     } else if (CFStringCompare(var, CFStringRef(QAXValueAttribute), 0) == kCFCompareEqualTo) {
1985         const QAccessible::Role role = interface.role();
1986         const QAccessible::Text text = (QAccessible::Text)textForRoleAndAttribute(role, var);
1987         if (role == QAccessible::CheckBox || role == QAccessible::RadioButton) {
1988             int value = buttonValue(interface);
1989             SetEventParameter(event, kEventParamAccessibleAttributeValue, typeUInt32, sizeof(value), &value);
1990         } else {
1991             handleStringAttribute(event, text, interface);
1992         }
1993     } else if (CFStringCompare(var, CFStringRef(QAXDescriptionAttribute), 0) == kCFCompareEqualTo) {
1994         const QAccessible::Role role = interface.role();
1995         const QAccessible::Text text = (QAccessible::Text)textForRoleAndAttribute(role, var);
1996         handleStringAttribute(event, text, interface);
1997     } else if (CFStringCompare(var, CFStringRef(QAXLinkedUIElementsAttribute), 0) == kCFCompareEqualTo) {
1998         return CallNextEventHandler(next_ref, event);
1999     } else if (CFStringCompare(var, CFStringRef(QAXHelpAttribute), 0) == kCFCompareEqualTo) {
2000         const QAccessible::Role role = interface.role();
2001         const QAccessible::Text text = (QAccessible::Text)textForRoleAndAttribute(role, var);
2002         handleStringAttribute(event, text, interface);
2003     } else if (CFStringCompare(var, kAXTitleUIElementAttribute, 0) == kCFCompareEqualTo) {
2004         return CallNextEventHandler(next_ref, event);
2005     } else if (CFStringCompare(var, CFStringRef(QAXTabsAttribute), 0) == kCFCompareEqualTo) {
2006         return handleTabsAttribute(next_ref, event, interface);
2007     } else if (CFStringCompare(var, CFStringRef(QAXMinValueAttribute), 0) == kCFCompareEqualTo) {
2008         // tabs we first go to the tab bar which is child #2.
2009         QAInterface tabBarInterface = interface.childAt(2);
2010         return handleTabsAttribute(next_ref, event, tabBarInterface);
2011     } else if (CFStringCompare(var, CFStringRef(QAXMinValueAttribute), 0) == kCFCompareEqualTo) {
2012         if (interface.role() == QAccessible::RadioButton || interface.role() == QAccessible::CheckBox) {
2013             uint value = 0;
2014             SetEventParameter(event, kEventParamAccessibleAttributeValue, typeUInt32, sizeof(value), &value);
2015         } else {
2016             return CallNextEventHandler(next_ref, event);
2017         }
2018     } else if (CFStringCompare(var, CFStringRef(QAXMaxValueAttribute), 0) == kCFCompareEqualTo) {
2019         if (interface.role() == QAccessible::RadioButton || interface.role() == QAccessible::CheckBox) {
2020             uint value = 2;
2021             SetEventParameter(event, kEventParamAccessibleAttributeValue, typeUInt32, sizeof(value), &value);
2022         } else {
2023             return CallNextEventHandler(next_ref, event);
2024         }
2025     } else if (CFStringCompare(var, CFStringRef(QAXOrientationAttribute), 0) == kCFCompareEqualTo) {
2026         return handleOrientationAttribute(next_ref, event, interface);
2027     } else if (CFStringCompare(var, CFStringRef(QAXPreviousContentsAttribute), 0) == kCFCompareEqualTo) {
2028         return handleSplitterContentsAttribute(next_ref, event, interface, CFStringRef(QAXPreviousContentsAttribute));
2029     } else if (CFStringCompare(var, CFStringRef(QAXNextContentsAttribute), 0) == kCFCompareEqualTo) {
2030         return handleSplitterContentsAttribute(next_ref, event, interface, CFStringRef(QAXNextContentsAttribute));
2031     } else if (CFStringCompare(var, CFStringRef(QAXSplittersAttribute), 0) == kCFCompareEqualTo) {
2032         return handleSplittersAttribute(next_ref, event, interface);
2033     } else if (CFStringCompare(var, CFStringRef(QAXHorizontalScrollBarAttribute), 0) == kCFCompareEqualTo) {
2034         return handleScrollBarAttribute(next_ref, event, interface, Qt::Horizontal);
2035     } else if (CFStringCompare(var, CFStringRef(QAXVerticalScrollBarAttribute), 0) == kCFCompareEqualTo) {
2036         return handleScrollBarAttribute(next_ref, event, interface, Qt::Vertical);
2037     } else if (CFStringCompare(var, CFStringRef(QAXContentsAttribute), 0) == kCFCompareEqualTo) {
2038         return handleContentsAttribute(next_ref, event, interface);
2039     } else if (CFStringCompare(var, CFStringRef(QAXRowsAttribute), 0) == kCFCompareEqualTo) {
2040         return handleRowsAttribute(next_ref, event, interface);
2041     } else if (CFStringCompare(var, CFStringRef(QAXVisibleRowsAttribute), 0) == kCFCompareEqualTo) {
2042         return handleVisibleRowsAttribute(next_ref, event, interface);
2043     } else if (CFStringCompare(var, CFStringRef(QAXSelectedRowsAttribute), 0) == kCFCompareEqualTo) {
2044         return handleSelectedRowsAttribute(next_ref, event, interface);
2045     } else {
2046         return CallNextEventHandler(next_ref, event);
2047     }
2048     return noErr;
2049 }
2050
2051 static OSStatus isNamedAttributeSettable(EventRef event, const QAInterface &interface)
2052 {
2053     CFStringRef var;
2054     GetEventParameter(event, kEventParamAccessibleAttributeName, typeCFStringRef, 0,
2055                       sizeof(var), 0, &var);
2056     Boolean settable = false;
2057     if (CFStringCompare(var, CFStringRef(QAXFocusedAttribute), 0) == kCFCompareEqualTo) {
2058         settable = true;
2059     } else {
2060         for (int r = 0; text_bindings[r][0].qt != -1; r++) {
2061             if(interface.role() == (QAccessible::Role)text_bindings[r][0].qt) {
2062                 for (int a = 1; text_bindings[r][a].qt != -1; a++) {
2063                     if (CFStringCompare(var, CFStringRef(text_bindings[r][a].mac), 0) == kCFCompareEqualTo) {
2064                         settable = text_bindings[r][a].settable;
2065                         break;
2066                     }
2067                 }
2068             }
2069         }
2070     }
2071     SetEventParameter(event, kEventParamAccessibleAttributeSettable, typeBoolean,
2072                       sizeof(settable), &settable);
2073     return noErr;
2074 }
2075
2076 static OSStatus getChildAtPoint(EventHandlerCallRef next_ref, EventRef event, QAInterface &interface)
2077 {
2078     Q_UNUSED(next_ref);
2079     if (interface.isValid() == false)
2080         return eventNotHandledErr;
2081
2082     // Add the children for this interface to the global QAccessibelHierachyManager.
2083     accessibleHierarchyManager()->registerChildren(interface);
2084
2085     Point where;
2086     GetEventParameter(event, kEventParamMouseLocation, typeQDPoint, 0, sizeof(where), 0, &where);
2087     const QAInterface childInterface = interface.childAt(where.h, where.v);
2088
2089     if (childInterface.isValid() == false || childInterface == interface)
2090         return eventNotHandledErr;
2091
2092     const QAElement element = accessibleHierarchyManager()->lookup(childInterface);
2093     if (element.isValid() == false)
2094         return eventNotHandledErr;
2095
2096     AXUIElementRef elementRef = element.element();
2097     CFRetain(elementRef);
2098     SetEventParameter(event, kEventParamAccessibleChild, typeCFTypeRef,
2099                                   sizeof(elementRef), &elementRef);
2100
2101     return noErr;
2102 }
2103
2104 /*
2105     Returns a list of actions the given interface supports.
2106     Currently implemented by getting the interface role and deciding based on that.
2107 */
2108 static QList<QAccessible::Action> supportedPredefinedActions(const QAInterface &interface)
2109 {
2110     QList<QAccessible::Action> actions;
2111     switch (interface.role()) {
2112         default:
2113             // Most things can be pressed.
2114             actions.append(QAccessible::Press);
2115         break;
2116     }
2117
2118     return actions;
2119 }
2120
2121 /*
2122     Translates a predefined QAccessible::Action to a Mac action constant.
2123     Returns an empty string if the Qt Action has no mac equivalent.
2124 */
2125 static QCFString translateAction(const QAccessible::Action action)
2126 {
2127     switch (action) {
2128         case QAccessible::Press:
2129             return CFStringRef(QAXPressAction);
2130         break;
2131         case QAccessible::Increase:
2132             return CFStringRef(QAXIncrementAction);
2133         break;
2134         case QAccessible::Decrease:
2135             return CFStringRef(QAXDecrementAction);
2136         break;
2137         case QAccessible::Accept:
2138             return CFStringRef(QAXConfirmAction);
2139         break;
2140         case QAccessible::Select:
2141             return CFStringRef(QAXPickAction);
2142         break;
2143         case QAccessible::Cancel:
2144             return CFStringRef(QAXCancelAction);
2145         break;
2146         default:
2147             return QCFString();
2148         break;
2149     }
2150 }
2151
2152 /*
2153     Translates between a Mac action constant and a QAccessible::Action.
2154     Returns QAccessible::Default action if there is no Qt predefined equivalent.
2155 */
2156 static QAccessible::Action translateAction(const CFStringRef actionName)
2157 {
2158     if(CFStringCompare(actionName, CFStringRef(QAXPressAction), 0) == kCFCompareEqualTo) {
2159         return QAccessible::Press;
2160     } else if(CFStringCompare(actionName, CFStringRef(QAXIncrementAction), 0) == kCFCompareEqualTo) {
2161         return QAccessible::Increase;
2162     } else if(CFStringCompare(actionName, CFStringRef(QAXDecrementAction), 0) == kCFCompareEqualTo) {
2163         return QAccessible::Decrease;
2164     } else if(CFStringCompare(actionName, CFStringRef(QAXConfirmAction), 0) == kCFCompareEqualTo) {
2165         return QAccessible::Accept;
2166     } else if(CFStringCompare(actionName, CFStringRef(QAXPickAction), 0) == kCFCompareEqualTo) {
2167         return QAccessible::Select;
2168     } else if(CFStringCompare(actionName, CFStringRef(QAXCancelAction), 0) == kCFCompareEqualTo) {
2169         return QAccessible::Cancel;
2170     } else {
2171         return QAccessible::DefaultAction;
2172     }
2173 }
2174 #endif // QT_MAC_USE_COCOA
2175
2176 /*
2177     Copies the translated names all supported actions for an interface into the kEventParamAccessibleActionNames
2178     event parameter.
2179 */
2180 #ifndef QT_MAC_USE_COCOA
2181 static OSStatus getAllActionNames(EventHandlerCallRef next_ref, EventRef event, const QAInterface &interface)
2182 {
2183     Q_UNUSED(next_ref);
2184
2185     CFMutableArrayRef actions = 0;
2186     GetEventParameter(event, kEventParamAccessibleActionNames, typeCFMutableArrayRef, 0,
2187                       sizeof(actions), 0, &actions);
2188
2189     // Add supported predefined actions.
2190     const QList<QAccessible::Action> predefinedActions = supportedPredefinedActions(interface);
2191     for (int i = 0; i < predefinedActions.count(); ++i) {
2192         const QCFString action = translateAction(predefinedActions.at(i));
2193         if (action != QCFString())
2194             qt_mac_append_cf_uniq(actions, action);
2195     }
2196
2197     // Add user actions
2198     const int actionCount = interface.userActionCount();
2199     for (int i = 0; i < actionCount; ++i) {
2200         const QString actionName = interface.actionText(i, QAccessible::Name);
2201         qt_mac_append_cf_uniq(actions, QCFString::toCFStringRef(actionName));
2202     }
2203
2204     return noErr;
2205 }
2206 #endif
2207
2208 /*
2209     Handles the perforNamedAction event.
2210 */
2211 #ifndef QT_MAC_USE_COCOA
2212 static OSStatus performNamedAction(EventHandlerCallRef next_ref, EventRef event, const QAInterface& interface)
2213 {
2214     Q_UNUSED(next_ref);
2215
2216     CFStringRef act;
2217     GetEventParameter(event, kEventParamAccessibleActionName, typeCFStringRef, 0,
2218                       sizeof(act), 0, &act);
2219
2220     const QAccessible::Action action = translateAction(act);
2221
2222     // Perform built-in action
2223     if (action != QAccessible::DefaultAction) {
2224         interface.doAction(action, QVariantList());
2225         return noErr;
2226     }
2227
2228     // Search for user-defined actions and perform it if found.
2229     const int actCount = interface.userActionCount();
2230     const QString qAct = QCFString::toQString(act);
2231     for(int i = 0; i < actCount; i++) {
2232         if(interface.actionText(i, QAccessible::Name) == qAct) {
2233             interface.doAction(i, QVariantList());
2234             break;
2235         }
2236     }
2237     return noErr;
2238 }
2239
2240 static OSStatus setNamedAttribute(EventHandlerCallRef next_ref, EventRef event, const QAInterface &interface)
2241 {
2242     Q_UNUSED(next_ref);
2243     Q_UNUSED(event);
2244
2245     CFStringRef var;
2246     GetEventParameter(event, kEventParamAccessibleAttributeName, typeCFStringRef, 0,
2247                       sizeof(var), 0, &var);
2248     if(CFStringCompare(var, CFStringRef(QAXFocusedAttribute), 0) == kCFCompareEqualTo) {
2249         CFTypeRef val;
2250         if(GetEventParameter(event, kEventParamAccessibleAttributeValue, typeCFTypeRef, 0,
2251                              sizeof(val), 0, &val) == noErr) {
2252             if(CFGetTypeID(val) == CFBooleanGetTypeID() &&
2253                CFEqual(static_cast<CFBooleanRef>(val), kCFBooleanTrue)) {
2254                 interface.doAction(QAccessible::SetFocus);
2255             }
2256         }
2257     } else {
2258         bool found = false;
2259         for(int r = 0; text_bindings[r][0].qt != -1; r++) {
2260             if(interface.role() == (QAccessible::Role)text_bindings[r][0].qt) {
2261                 for(int a = 1; text_bindings[r][a].qt != -1; a++) {
2262                     if(CFStringCompare(var, CFStringRef(text_bindings[r][a].mac), 0) == kCFCompareEqualTo) {
2263                         if(!text_bindings[r][a].settable) {
2264                         } else {
2265                             CFTypeRef val;
2266                             if(GetEventParameter(event, kEventParamAccessibleAttributeValue, typeCFTypeRef, 0,
2267                                                  sizeof(val), 0, &val) == noErr) {
2268                                 if(CFGetTypeID(val) == CFStringGetTypeID())
2269                                     interface.setText((QAccessible::Text)text_bindings[r][a].qt,
2270                                                    QCFString::toQString(static_cast<CFStringRef>(val)));
2271
2272                             }
2273                         }
2274                         found = true;
2275                         break;
2276                     }
2277                 }
2278                 break;
2279             }
2280         }
2281     }
2282     return noErr;
2283 }
2284
2285 /*
2286     This is the main accessibility event handler.
2287 */
2288 static OSStatus accessibilityEventHandler(EventHandlerCallRef next_ref, EventRef event, void *data)
2289 {
2290     Q_UNUSED(data)
2291
2292     // Return if this event is not a AccessibleGetNamedAttribute event.
2293     const UInt32 eclass = GetEventClass(event);
2294     if (eclass != kEventClassAccessibility)
2295         return eventNotHandledErr;
2296
2297     // Get the AXUIElementRef and QAInterface pointer
2298     AXUIElementRef element = 0;
2299     GetEventParameter(event, kEventParamAccessibleObject, typeCFTypeRef, 0, sizeof(element), 0, &element);
2300     QAInterface interface = accessibleHierarchyManager()->lookup(element);
2301     if (interface.isValid() == false)
2302         return eventNotHandledErr;
2303
2304     const UInt32 ekind = GetEventKind(event);
2305     OSStatus status = noErr;
2306     switch (ekind) {
2307         case kEventAccessibleGetAllAttributeNames:
2308              status = getAllAttributeNames(event, interface, next_ref);
2309         break;
2310         case kEventAccessibleGetNamedAttribute:
2311              status = getNamedAttribute(next_ref, event, interface);
2312         break;
2313         case kEventAccessibleIsNamedAttributeSettable:
2314              status = isNamedAttributeSettable(event, interface);
2315         break;
2316         case kEventAccessibleGetChildAtPoint:
2317             status = getChildAtPoint(next_ref, event, interface);
2318         break;
2319         case kEventAccessibleGetAllActionNames:
2320             status = getAllActionNames(next_ref, event, interface);
2321         break;
2322         case kEventAccessibleGetFocusedChild:
2323             status = CallNextEventHandler(next_ref, event);
2324         break;
2325         case kEventAccessibleSetNamedAttribute:
2326             status = setNamedAttribute(next_ref, event, interface);
2327         break;
2328         case kEventAccessiblePerformNamedAction:
2329             status = performNamedAction(next_ref, event, interface);
2330         break;
2331         default:
2332             status = CallNextEventHandler(next_ref, event);
2333         break;
2334     };
2335     return status;
2336 }
2337 #endif
2338
2339 void QAccessible::initialize()
2340 {
2341 #ifndef QT_MAC_USE_COCOA
2342     registerQtAccessibilityHIObjectSubclass();
2343     installApplicationEventhandler();
2344 #endif
2345 }
2346
2347 // Sets thre root object for the application
2348 void QAccessible::setRootObject(QObject *object)
2349 {
2350     // Call installed root object handler if we have one
2351     if (rootObjectHandler) {
2352         rootObjectHandler(object);
2353         return;
2354     }
2355
2356     rootObject = object;
2357 }
2358
2359 void QAccessible::cleanup()
2360 {
2361     accessibleHierarchyManager()->reset();
2362 #ifndef QT_MAC_USE_COCOA
2363     removeEventhandler(applicationEventHandlerUPP);
2364     removeEventhandler(objectCreateEventHandlerUPP);
2365     removeEventhandler(accessibilityEventHandlerUPP);
2366 #endif
2367 }
2368
2369 void QAccessible::updateAccessibility(QObject *object, int child, Event reason)
2370 {
2371     // Call installed update handler if we have one.
2372     if (updateHandler) {
2373         updateHandler(object, child, reason);
2374         return;
2375     }
2376
2377 #ifndef QT_MAC_USE_COCOA
2378     // Return if the mac accessibility is not enabled.
2379     if(!AXAPIEnabled())
2380         return;
2381
2382      // Work around crash, disable accessiblity for focus frames.
2383      if (qstrcmp(object->metaObject()->className(), "QFocusFrame") == 0)
2384         return;
2385
2386 //    qDebug() << "updateAccessibility" << object << child << hex << reason;
2387
2388     if (reason == ObjectShow) {
2389         QAInterface interface = QAInterface(QAccessible::queryAccessibleInterface(object), child);
2390         accessibleHierarchyManager()->registerInterface(interface);
2391     }
2392
2393     const QAElement element = accessibleHierarchyManager()->lookup(object, child);
2394     if (element.isValid() == false)
2395         return;
2396
2397
2398     CFStringRef notification = 0;
2399     if(object && object->isWidgetType() && reason == ObjectCreated) {
2400         notification = CFStringRef(QAXWindowCreatedNotification);
2401     } else if(reason == ValueChanged) {
2402         notification = CFStringRef(QAXValueChangedNotification);
2403     } else if(reason == MenuStart) {
2404         notification = CFStringRef(QAXMenuOpenedNotification);
2405     } else if(reason == MenuEnd) {
2406         notification = CFStringRef(QAXMenuClosedNotification);
2407     } else if(reason == LocationChanged) {
2408         notification = CFStringRef(QAXWindowMovedNotification);
2409     } else if(reason == ObjectShow || reason == ObjectHide ) {
2410         // When a widget is deleted we get a ObjectHide before the destroyed(QObject *)
2411         // signal is emitted (which makes sense). However, at this point we are in the
2412         // middle of the QWidget destructor which means that we have to be careful when
2413         // using the widget pointer. Since we can't control what the accessibilty interfaces
2414         // does when navigate() is called below we ignore the hide update in this case.
2415         // (the widget will be deleted soon anyway.)
2416         extern QWidgetPrivate * qt_widget_private(QWidget *);
2417         if (QWidget *widget = qobject_cast<QWidget*>(object)) {
2418             if (qt_widget_private(widget)->data.in_destructor)
2419                 return;
2420
2421             // Check widget parent as well, special case for preventing crash
2422             // when the viewport() of an abstract scroll area is hidden when
2423             // the QWidget destructor hides all its children.
2424             QWidget *parentWidget = widget->parentWidget();
2425             if (parentWidget && qt_widget_private(parentWidget)->data.in_destructor)
2426                 return;
2427         }
2428
2429         // There is no equivalent Mac notification for ObjectShow/Hide, so we call HIObjectSetAccessibilityIgnored
2430         // and isItInteresting which will mark the HIObject accociated with the element as ignored if the
2431         // QAccessible::Invisible state bit is set.
2432         QAInterface interface = accessibleHierarchyManager()->lookup(element);
2433         if (interface.isValid()) {
2434             HIObjectSetAccessibilityIgnored(element.object(), !isItInteresting(interface));
2435         }
2436
2437         // If the interface manages its own children, also check if we should ignore those.
2438         if (isItemView(interface) == false && managesChildren(interface)) {
2439             for (int i = 1; i <= interface.childCount(); ++i) {
2440                 QAInterface childInterface = interface.navigate(QAccessible::Child, i);
2441                 if (childInterface.isValid() && childInterface.isHIView() == false) {
2442                     const QAElement element = accessibleHierarchyManager()->lookup(childInterface);
2443                     if (element.isValid()) {
2444                         HIObjectSetAccessibilityIgnored(element.object(), !isItInteresting(childInterface));
2445                     }
2446                 }
2447             }
2448         }
2449
2450     } else if(reason == Focus) {
2451         if(object && object->isWidgetType()) {
2452             QWidget *w = static_cast<QWidget*>(object);
2453             if(w->isWindow())
2454                 notification = CFStringRef(QAXFocusedWindowChangedNotification);
2455             else
2456                 notification = CFStringRef(QAXFocusedUIElementChangedNotification);
2457         }
2458     }
2459
2460     if (!notification)
2461         return;
2462
2463     AXNotificationHIObjectNotify(notification, element.object(), element.id());
2464 #endif
2465 }
2466
2467 QT_END_NAMESPACE
2468
2469 #endif // QT_NO_ACCESSIBILITY