src/gui/accessible/qaccessible_mac.mm
changeset 0 1918ee327afb
child 3 41300fa6a67c
equal deleted inserted replaced
-1:000000000000 0:1918ee327afb
       
     1 /****************************************************************************
       
     2 **
       
     3 ** Copyright (C) 2009 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 ** No Commercial Usage
       
    11 ** This file contains pre-release code and may not be distributed.
       
    12 ** You may use this file in accordance with the terms and conditions
       
    13 ** contained in the Technology Preview License Agreement accompanying
       
    14 ** this package.
       
    15 **
       
    16 ** GNU Lesser General Public License Usage
       
    17 ** Alternatively, this file may be used under the terms of the GNU Lesser
       
    18 ** General Public License version 2.1 as published by the Free Software
       
    19 ** Foundation and appearing in the file LICENSE.LGPL included in the
       
    20 ** packaging of this file.  Please review the following information to
       
    21 ** ensure the GNU Lesser General Public License version 2.1 requirements
       
    22 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
       
    23 **
       
    24 ** In addition, as a special exception, Nokia gives you certain additional
       
    25 ** rights.  These rights are described in the Nokia Qt LGPL Exception
       
    26 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
       
    27 **
       
    28 ** If you have questions regarding the use of this file, please contact
       
    29 ** Nokia at qt-info@nokia.com.
       
    30 **
       
    31 **
       
    32 **
       
    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     :elementRef(
       
   508 #ifndef QT_MAC_USE_COCOA
       
   509                 AXUIElementCreateWithHIObjectAndIdentifier(object, child)
       
   510 #endif
       
   511 )
       
   512 {
       
   513 #ifndef QT_MAC_USE_COCOA
       
   514     if (object == 0) {
       
   515         elementRef = 0; // Create invalid QAElement.
       
   516     } else {
       
   517         elementRef = AXUIElementCreateWithHIObjectAndIdentifier(object, child);
       
   518         CFRetain(object);
       
   519     }
       
   520 #else
       
   521     Q_UNUSED(object);
       
   522     Q_UNUSED(child);
       
   523 #endif
       
   524 }
       
   525 
       
   526 QAElement::~QAElement()
       
   527 {
       
   528     if (elementRef != 0) {
       
   529         CFRelease(object());
       
   530         CFRelease(elementRef);
       
   531     }
       
   532 }
       
   533 
       
   534 void QAElement::operator=(const QAElement &other)
       
   535 {
       
   536     if (*this == other)
       
   537         return;
       
   538 
       
   539     if (elementRef != 0) {
       
   540         CFRelease(object());
       
   541         CFRelease(elementRef);
       
   542     }
       
   543 
       
   544     elementRef = other.elementRef;
       
   545 
       
   546     if (elementRef != 0) {
       
   547         CFRetain(elementRef);
       
   548         CFRetain(object());
       
   549     }
       
   550 }
       
   551 
       
   552 bool QAElement::operator==(const QAElement &other) const
       
   553 {
       
   554     if (elementRef == 0 || other.elementRef == 0)
       
   555         return (elementRef == other.elementRef);
       
   556 
       
   557     return CFEqual(elementRef, other.elementRef);
       
   558 }
       
   559 
       
   560 uint qHash(QAElement element)
       
   561 {
       
   562     return qHash(element.object()) + qHash(element.id());
       
   563 }
       
   564 
       
   565 #ifndef QT_MAC_USE_COCOA
       
   566 static QInterfaceFactory *createFactory(const QAInterface &interface);
       
   567 #endif
       
   568 Q_GLOBAL_STATIC(QAccessibleHierarchyManager, accessibleHierarchyManager);
       
   569 
       
   570 /*
       
   571     Reomves all accessibility info accosiated with the sender object.
       
   572 */
       
   573 void QAccessibleHierarchyManager::objectDestroyed(QObject *object)
       
   574 {
       
   575     HIObjectRef hiObject = qobjectHiobjectHash.value(object);
       
   576     delete qobjectElementHash.value(object);
       
   577     qobjectElementHash.remove(object);
       
   578     hiobjectInterfaceHash.remove(hiObject);
       
   579 }
       
   580 
       
   581 /*
       
   582     Removes all stored items.
       
   583 */
       
   584 void QAccessibleHierarchyManager::reset()
       
   585 {
       
   586     qDeleteAll(qobjectElementHash);
       
   587     qobjectElementHash.clear();
       
   588     hiobjectInterfaceHash.clear();
       
   589     qobjectHiobjectHash.clear();
       
   590 }
       
   591 
       
   592 QAccessibleHierarchyManager *QAccessibleHierarchyManager::instance()
       
   593 {
       
   594     return accessibleHierarchyManager();
       
   595 }
       
   596 
       
   597 #ifndef QT_MAC_USE_COCOA
       
   598 static bool isItemView(const QAInterface &interface)
       
   599 {
       
   600     QObject *object = interface.object();
       
   601     return (interface.role() == QAccessible::List || interface.role() == QAccessible::Table
       
   602             || (object && qobject_cast<QAbstractItemView *>(interface.object()))
       
   603             || (object && object->objectName() == QLatin1String("qt_scrollarea_viewport")
       
   604                 && qobject_cast<QAbstractItemView *>(object->parent())));
       
   605 }
       
   606 #endif
       
   607 
       
   608 static bool isTabWidget(const QAInterface &interface)
       
   609 {
       
   610     if (QObject *object = interface.object())
       
   611         return (object->inherits("QTabWidget") && interface.id() == 0);
       
   612     return false;
       
   613 }
       
   614 
       
   615 static bool isStandaloneTabBar(const QAInterface &interface)
       
   616 {
       
   617     QObject *object = interface.object();
       
   618     if (interface.role() == QAccessible::PageTabList && object)
       
   619         return (qobject_cast<QTabWidget *>(object->parent()) == 0);
       
   620 
       
   621     return false;
       
   622 }
       
   623 
       
   624 static bool isEmbeddedTabBar(const QAInterface &interface)
       
   625 {
       
   626     QObject *object = interface.object();
       
   627     if (interface.role() == QAccessible::PageTabList && object)
       
   628         return (qobject_cast<QTabWidget *>(object->parent()));
       
   629 
       
   630     return false;
       
   631 }
       
   632 
       
   633 /*
       
   634     Decides if a QAInterface is interesting from an accessibility users point of view.
       
   635 */
       
   636 bool isItInteresting(const QAInterface &interface)
       
   637 {
       
   638     // Mac accessibility does not have an attribute that corresponds to the Invisible/Offscreen
       
   639     // state, so we disable the interface here.
       
   640     const QAccessible::State state = interface.state();
       
   641     if (state & QAccessible::Invisible ||
       
   642         state & QAccessible::Offscreen )
       
   643         return false;
       
   644 
       
   645     const QAccessible::Role role = interface.role();
       
   646 
       
   647     if (QObject * const object = interface.object()) {
       
   648         const QString className = QLatin1String(object->metaObject()->className());
       
   649 
       
   650         // VoiceOver focusing on tool tips can be confusing. The contents of the
       
   651         // tool tip is avalible through the description attribute anyway, so
       
   652         // we disable accessibility for tool tips.
       
   653         if (className == QLatin1String("QTipLabel"))
       
   654             return false;
       
   655 
       
   656         // Hide TabBars that has a QTabWidget parent (the tab widget handles the accessibility)
       
   657         if (isEmbeddedTabBar(interface))
       
   658             return false;
       
   659 
       
   660          // Hide docked dockwidgets. ### causes infinitie loop in the apple accessibility code.
       
   661      /*    if (QDockWidget *dockWidget = qobject_cast<QDockWidget *>(object)) {
       
   662             if (dockWidget->isFloating() == false)
       
   663                 return false;        
       
   664          }
       
   665     */
       
   666     }
       
   667 
       
   668     // Client is a generic role returned by plain QWidgets or other
       
   669     // widgets that does not have separate QAccessible interface, such
       
   670     // as the TabWidget. Return false unless macRole gives the interface
       
   671     // a special role.
       
   672     if (role == QAccessible::Client && macRole(interface) == CFStringRef(QAXUnknownRole))
       
   673         return false;
       
   674 
       
   675     // Some roles are not interesting:
       
   676     if (role == QAccessible::Border ||    // QFrame
       
   677         role == QAccessible::Application || // We use the system-provided application element.
       
   678         role == QAccessible::MenuItem)      // The system also provides the menu items.
       
   679         return false;
       
   680 
       
   681     // It is probably better to access the toolbar buttons directly than having
       
   682     // to navigate through the toolbar.
       
   683     if (role == QAccessible::ToolBar)
       
   684         return false;
       
   685 
       
   686     return true;
       
   687 }
       
   688 
       
   689 QAElement QAccessibleHierarchyManager::registerInterface(QObject *object, int child)
       
   690 {
       
   691 #ifndef QT_MAC_USE_COCOA
       
   692     return registerInterface(QAInterface(QAccessible::queryAccessibleInterface(object), child));
       
   693 #else
       
   694     Q_UNUSED(object);
       
   695     Q_UNUSED(child);
       
   696     return QAElement();
       
   697 #endif
       
   698 }
       
   699 
       
   700 /*
       
   701     Creates a QAXUIelement that corresponds to the given QAInterface.
       
   702 */
       
   703 QAElement QAccessibleHierarchyManager::registerInterface(const QAInterface &interface)
       
   704 {
       
   705 #ifndef QT_MAC_USE_COCOA
       
   706     if (interface.isValid() == false)
       
   707         return QAElement();
       
   708     QAInterface objectInterface = interface.objectInterface();
       
   709 
       
   710     QObject * qobject = objectInterface.object();
       
   711     HIObjectRef hiobject = objectInterface.hiObject();
       
   712     if (qobject == 0 || hiobject == 0)
       
   713         return QAElement();
       
   714 
       
   715     if (qobjectElementHash.contains(qobject) == false) {
       
   716         registerInterface(qobject, hiobject, createFactory(interface));
       
   717         HIObjectSetAccessibilityIgnored(hiobject, !isItInteresting(interface));
       
   718     }
       
   719 
       
   720     return QAElement(hiobject, interface.id());
       
   721 #else
       
   722     Q_UNUSED(interface);
       
   723     return QAElement();
       
   724 #endif
       
   725 }
       
   726 
       
   727 #ifndef QT_MAC_USE_COCOA
       
   728 #include "qaccessible_mac_carbon.cpp"
       
   729 #endif
       
   730 
       
   731 void QAccessibleHierarchyManager::registerInterface(QObject * qobject, HIObjectRef hiobject, QInterfaceFactory *interfaceFactory)
       
   732 {
       
   733 #ifndef QT_MAC_USE_COCOA
       
   734     if (qobjectElementHash.contains(qobject) == false) {
       
   735         qobjectElementHash.insert(qobject, interfaceFactory);
       
   736         qobjectHiobjectHash.insert(qobject, hiobject);
       
   737         connect(qobject, SIGNAL(destroyed(QObject *)), SLOT(objectDestroyed(QObject *)));
       
   738     }
       
   739 
       
   740     if (hiobjectInterfaceHash.contains(hiobject) == false) {
       
   741         hiobjectInterfaceHash.insert(hiobject, interfaceFactory);
       
   742         installAcessibilityEventHandler(hiobject);
       
   743     }
       
   744 #else
       
   745     Q_UNUSED(qobject);
       
   746     Q_UNUSED(hiobject);
       
   747     Q_UNUSED(interfaceFactory);
       
   748 #endif
       
   749 }
       
   750 
       
   751 void QAccessibleHierarchyManager::registerChildren(const QAInterface &interface)
       
   752 {
       
   753     QObject * const object = interface.object();
       
   754     if (object == 0)
       
   755         return;
       
   756 
       
   757     QInterfaceFactory *interfaceFactory = qobjectElementHash.value(object);
       
   758     
       
   759     if (interfaceFactory == 0)
       
   760         return;
       
   761 
       
   762     interfaceFactory->registerChildren();
       
   763 }
       
   764 
       
   765 QAInterface QAccessibleHierarchyManager::lookup(const AXUIElementRef &element)
       
   766 {
       
   767      if (element == 0)
       
   768         return QAInterface();
       
   769 #ifndef QT_MAC_USE_COCOA
       
   770     HIObjectRef hiObject = AXUIElementGetHIObject(element);
       
   771 
       
   772     QInterfaceFactory *factory = hiobjectInterfaceHash.value(hiObject);
       
   773     if (factory == 0) {
       
   774         return QAInterface();
       
   775     }
       
   776 
       
   777     UInt64 id;
       
   778     AXUIElementGetIdentifier(element, &id);
       
   779     return factory->interface(id);
       
   780 #else
       
   781     return QAInterface();
       
   782 #endif;
       
   783 }
       
   784 
       
   785 QAInterface QAccessibleHierarchyManager::lookup(const QAElement &element)
       
   786 {
       
   787     return lookup(element.element());
       
   788 }
       
   789 
       
   790 QAElement QAccessibleHierarchyManager::lookup(const QAInterface &interface)
       
   791 {
       
   792     if (interface.isValid() == false)
       
   793         return QAElement();
       
   794 
       
   795     QInterfaceFactory *factory = qobjectElementHash.value(interface.objectInterface().object());
       
   796     if (factory == 0)
       
   797         return QAElement();
       
   798 
       
   799     return factory->element(interface);
       
   800 }
       
   801 
       
   802 QAElement QAccessibleHierarchyManager::lookup(QObject * const object, int id)
       
   803 {
       
   804     QInterfaceFactory *factory = qobjectElementHash.value(object);
       
   805     if (factory == 0)
       
   806         return QAElement();
       
   807 
       
   808     return factory->element(id);
       
   809 }
       
   810 
       
   811 /*
       
   812     Standard interface mapping, return the stored interface
       
   813     or HIObjectRef, and there is an one-to-one mapping between
       
   814     the identifier and child.
       
   815 */
       
   816 class QStandardInterfaceFactory : public QInterfaceFactory
       
   817 {
       
   818 public:
       
   819     QStandardInterfaceFactory(const QAInterface &interface)
       
   820     : m_interface(interface), object(interface.hiObject())
       
   821     {
       
   822         CFRetain(object);
       
   823     }
       
   824     
       
   825     ~QStandardInterfaceFactory()
       
   826     {
       
   827          CFRelease(object);
       
   828     }
       
   829 
       
   830     
       
   831     QAInterface interface(UInt64 identifier)
       
   832     {
       
   833         const int child = identifier;
       
   834         return QAInterface(m_interface, child);
       
   835     }
       
   836 
       
   837     QAElement element(int id)
       
   838     {
       
   839         return QAElement(object, id);
       
   840     }
       
   841 
       
   842     QAElement element(const QAInterface &interface)
       
   843     {
       
   844         if (interface.object() == 0)
       
   845             return QAElement();
       
   846         return QAElement(object, interface.id());
       
   847     }
       
   848 
       
   849     void registerChildren()
       
   850     {
       
   851         const int childCount = m_interface.childCount();
       
   852         for (int i = 1; i <= childCount; ++i) {
       
   853             accessibleHierarchyManager()->registerInterface(m_interface.navigate(QAccessible::Child, i));
       
   854         }
       
   855     }
       
   856 
       
   857 private:
       
   858     QAInterface m_interface;
       
   859     HIObjectRef object;
       
   860 };
       
   861 
       
   862 /*
       
   863     Interface mapping where that creates one HIObject for each interface child.
       
   864 */
       
   865 class QMultipleHIObjectFactory : public QInterfaceFactory
       
   866 {
       
   867 public:
       
   868     QMultipleHIObjectFactory(const QAInterface &interface)
       
   869     : m_interface(interface)
       
   870     {  }
       
   871     
       
   872     ~QMultipleHIObjectFactory()
       
   873     {
       
   874         foreach (HIObjectRef object, objects) {
       
   875             CFRelease(object);
       
   876         }
       
   877     }
       
   878 
       
   879     QAInterface interface(UInt64 identifier)
       
   880     {
       
   881         const int child = identifier;
       
   882         return QAInterface(m_interface, child);
       
   883     }
       
   884 
       
   885     QAElement element(int child)
       
   886     {
       
   887         if (child == 0)
       
   888             return QAElement(m_interface.hiObject(), 0);
       
   889         
       
   890         if (child > objects.count())
       
   891             return QAElement();
       
   892 
       
   893         return QAElement(objects.at(child - 1), child);
       
   894     }
       
   895 
       
   896     void registerChildren()
       
   897     {
       
   898 #ifndef QT_MAC_USE_COCOA
       
   899         const int childCount = m_interface.childCount();
       
   900         for (int i = 1; i <= childCount; ++i) {
       
   901             HIObjectRef hiobject;
       
   902             HIObjectCreate(kObjectQtAccessibility, 0, &hiobject);
       
   903             objects.append(hiobject);
       
   904               accessibleHierarchyManager()->registerInterface(m_interface.object(), hiobject, this);
       
   905             HIObjectSetAccessibilityIgnored(hiobject, !isItInteresting(m_interface.navigate(QAccessible::Child, i)));
       
   906         }
       
   907 #endif
       
   908     }
       
   909 
       
   910 private:
       
   911     QAInterface m_interface;
       
   912     QList<HIObjectRef> objects;
       
   913 };
       
   914 
       
   915 class QItemViewInterfaceFactory : public QInterfaceFactory
       
   916 {
       
   917 public:
       
   918     QItemViewInterfaceFactory(const QAInterface &interface)
       
   919     : m_interface(interface), object(interface.hiObject())
       
   920     {
       
   921         CFRetain(object);
       
   922         columnCount = 0;
       
   923         if (QTableView * tableView = qobject_cast<QTableView *>(interface.parent().object())) {
       
   924             if (tableView->model())
       
   925                 columnCount = tableView->model()->columnCount();
       
   926             if (tableView->verticalHeader())
       
   927                 ++columnCount;
       
   928         }
       
   929     }
       
   930     
       
   931     ~QItemViewInterfaceFactory()
       
   932     {
       
   933         CFRelease(object);
       
   934     }
       
   935 
       
   936     QAInterface interface(UInt64 identifier)
       
   937     {
       
   938         if (identifier == 0)
       
   939             return m_interface;
       
   940 
       
   941         if (m_interface.role() == QAccessible::List)
       
   942             return m_interface.childAt(identifier);
       
   943         
       
   944         if (m_interface.role() == QAccessible::Table) {
       
   945             const int index = identifier;
       
   946             if (index == 0)
       
   947                 return m_interface; // return the item view interface.
       
   948            
       
   949             const int rowIndex = (index - 1) / (columnCount + 1);
       
   950             const int cellIndex = (index - 1)  % (columnCount + 1);
       
   951 /*
       
   952             qDebug() << "index" << index;
       
   953             qDebug() << "rowIndex" << rowIndex;
       
   954             qDebug() << "cellIndex" << cellIndex;
       
   955 */
       
   956             const QAInterface rowInterface = m_interface.childAt(rowIndex + 1);
       
   957 
       
   958             if ((cellIndex) == 0) // Is it a row?
       
   959                 return rowInterface;
       
   960             else {
       
   961                 return rowInterface.childAt(cellIndex);
       
   962             }
       
   963         }
       
   964 
       
   965         return QAInterface();
       
   966     }
       
   967 
       
   968     QAElement element(int id)
       
   969     {
       
   970         if (id != 0) {
       
   971             return QAElement();
       
   972         }
       
   973         return QAElement(object, 0);
       
   974     }
       
   975 
       
   976     QAElement element(const QAInterface &interface)
       
   977     {
       
   978         if (interface.object() && interface.object() == m_interface.object()) {
       
   979             return QAElement(object, 0);
       
   980         } else if (m_interface.role() == QAccessible::List) {
       
   981             if (interface.parent().object() && interface.parent().object() == m_interface.object())
       
   982                 return QAElement(object, m_interface.indexOfChild(interface));
       
   983         } else if (m_interface.role() == QAccessible::Table) {
       
   984             QAInterface currentInterface = interface;
       
   985             int index = 0;
       
   986 
       
   987             while (currentInterface.isValid() && currentInterface.object() == 0) {
       
   988                 const QAInterface parentInterface = currentInterface.parent();
       
   989 /*
       
   990                 qDebug() << "current index" << index;
       
   991                 qDebug() << "current interface" << interface;
       
   992 
       
   993                 qDebug() << "parent interface" << parentInterface;
       
   994                 qDebug() << "grandparent interface" << parentInterface.parent();
       
   995                 qDebug() << "childCount" << interface.childCount();
       
   996                 qDebug() << "index of child" << parentInterface.indexOfChild(currentInterface);
       
   997 */
       
   998                 index += ((parentInterface.indexOfChild(currentInterface) - 1) * (currentInterface.childCount() + 1)) + 1;
       
   999                 currentInterface = parentInterface;
       
  1000 //                qDebug() << "new current interface" << currentInterface;
       
  1001             }
       
  1002             if (currentInterface.object() == m_interface.object())
       
  1003                 return QAElement(object, index);
       
  1004 
       
  1005 
       
  1006         }
       
  1007         return QAElement();
       
  1008     }
       
  1009 
       
  1010     void registerChildren()
       
  1011     {
       
  1012         // Item view child interfraces don't have their own qobjects, so there is nothing to register here.
       
  1013     }
       
  1014 
       
  1015 private:
       
  1016     QAInterface m_interface;
       
  1017     HIObjectRef object;
       
  1018     int columnCount; // for table views;
       
  1019 };
       
  1020 
       
  1021 #ifndef QT_MAC_USE_COCOA
       
  1022 static bool managesChildren(const QAInterface &interface)
       
  1023 {
       
  1024     return (interface.childCount() > 0 && interface.childAt(1).id() > 0);
       
  1025 }
       
  1026 
       
  1027 static QInterfaceFactory *createFactory(const QAInterface &interface)
       
  1028 {
       
  1029     if (isItemView(interface)) {
       
  1030         return new QItemViewInterfaceFactory(interface);
       
  1031     }  if (managesChildren(interface)) {
       
  1032         return new QMultipleHIObjectFactory(interface);
       
  1033     }
       
  1034 
       
  1035     return new QStandardInterfaceFactory(interface);
       
  1036 }
       
  1037 #endif
       
  1038 
       
  1039 QList<QAElement> lookup(const QList<QAInterface> &interfaces)
       
  1040 {
       
  1041     QList<QAElement> elements;
       
  1042     foreach (const QAInterface &interface, interfaces)
       
  1043         if (interface.isValid()) {
       
  1044             const QAElement element = accessibleHierarchyManager()->lookup(interface);
       
  1045             if (element.isValid())
       
  1046                 elements.append(element);
       
  1047         }
       
  1048     return elements;
       
  1049 }
       
  1050 
       
  1051 // Debug output helpers:
       
  1052 /*
       
  1053 static QString nameForEventKind(UInt32 kind)
       
  1054 {
       
  1055     switch(kind) {
       
  1056         case kEventAccessibleGetChildAtPoint:       return QString("GetChildAtPoint");      break;
       
  1057         case kEventAccessibleGetAllAttributeNames:  return QString("GetAllAttributeNames"); break;
       
  1058         case kEventAccessibleGetNamedAttribute:     return QString("GetNamedAttribute");    break;
       
  1059         case kEventAccessibleSetNamedAttribute:     return QString("SetNamedAttribute");    break;
       
  1060         case kEventAccessibleGetAllActionNames:     return QString("GetAllActionNames");    break;
       
  1061         case kEventAccessibleGetFocusedChild:       return QString("GetFocusedChild");      break;
       
  1062         default:
       
  1063             return QString("Unknown accessibility event type: %1").arg(kind);
       
  1064         break;
       
  1065     };
       
  1066 }
       
  1067 */
       
  1068 #ifndef QT_MAC_USE_COCOA
       
  1069 static bool qt_mac_append_cf_uniq(CFMutableArrayRef array, CFTypeRef value)
       
  1070 {
       
  1071     if (value == 0)
       
  1072         return false; 
       
  1073 
       
  1074     CFRange range;
       
  1075     range.location = 0;
       
  1076     range.length = CFArrayGetCount(array);
       
  1077     if(!CFArrayContainsValue(array, range, value)) {
       
  1078         CFArrayAppendValue(array, value);
       
  1079         return true;
       
  1080     }
       
  1081     return false;
       
  1082 }
       
  1083 
       
  1084 static OSStatus setAttributeValue(EventRef event, const QList<QAElement> &elements)
       
  1085 {
       
  1086     CFMutableArrayRef array = CFArrayCreateMutable(0, 0, &kCFTypeArrayCallBacks);
       
  1087     foreach (const QAElement &element, elements) {
       
  1088         if (element.isValid())
       
  1089             CFArrayAppendValue(array, element.element());
       
  1090     }
       
  1091 
       
  1092     const OSStatus err = SetEventParameter(event, kEventParamAccessibleAttributeValue, 
       
  1093                                            typeCFTypeRef, sizeof(array), &array);
       
  1094     CFRelease(array);
       
  1095     return err;
       
  1096 }
       
  1097 #endif //QT_MAC_USE_COCOA
       
  1098 
       
  1099 /*
       
  1100     Gets the AccessibleObject parameter from an event.
       
  1101 */
       
  1102 static inline AXUIElementRef getAccessibleObjectParameter(EventRef event)
       
  1103 {
       
  1104     AXUIElementRef element;
       
  1105     GetEventParameter(event, kEventParamAccessibleObject, typeCFTypeRef, 0,
       
  1106                         sizeof(element), 0, &element);
       
  1107     return element;
       
  1108 }
       
  1109 
       
  1110 /*
       
  1111     The application event handler makes sure that all top-level qt windows are registered
       
  1112     before any accessibility events are handeled.
       
  1113 */
       
  1114 #ifndef QT_MAC_USE_COCOA
       
  1115 static OSStatus applicationEventHandler(EventHandlerCallRef next_ref, EventRef event, void *)
       
  1116 {
       
  1117     QAInterface rootInterface(QAccessible::queryAccessibleInterface(rootObject ? rootObject : qApp), 0);
       
  1118     accessibleHierarchyManager()->registerChildren(rootInterface);
       
  1119 
       
  1120     return CallNextEventHandler(next_ref, event);
       
  1121 }
       
  1122 
       
  1123 /*
       
  1124     Returns the value for element by combining the QAccessibility::Checked and
       
  1125     QAccessibility::Mixed flags into an int value that the Mac accessibilty
       
  1126     system understands. This works for check boxes, radio buttons, and the like.
       
  1127     The return values are:
       
  1128     0: unchecked
       
  1129     1: checked
       
  1130     2: undecided
       
  1131 */
       
  1132 static int buttonValue(QAInterface element)
       
  1133 {
       
  1134     const QAccessible::State state = element.state();
       
  1135     if (state & QAccessible::Mixed)
       
  1136         return 2;
       
  1137     else if(state & QAccessible::Checked)
       
  1138         return 1;
       
  1139     else
       
  1140         return 0;
       
  1141 }
       
  1142 
       
  1143 static QString getValue(const QAInterface &interface)
       
  1144 {
       
  1145     const QAccessible::Role role = interface.role();
       
  1146     if (role == QAccessible::RadioButton || role == QAccessible::CheckBox)
       
  1147         return QString::number(buttonValue(interface));
       
  1148     else
       
  1149         return interface.text(QAccessible::Value);
       
  1150 }
       
  1151 #endif //QT_MAC_USE_COCOA
       
  1152 
       
  1153 /*
       
  1154     Translates a QAccessible::Role into a mac accessibility role.
       
  1155 */
       
  1156 static CFStringRef macRole(const QAInterface &interface)
       
  1157 {
       
  1158     const QAccessible::Role qtRole = interface.role();
       
  1159 
       
  1160 //    qDebug() << "role for" << interface.object() << "interface role" << hex << qtRole;
       
  1161 
       
  1162     // Qt accessibility:  QAccessible::Splitter contains QAccessible::Grip.
       
  1163     // Mac accessibility: AXSplitGroup contains AXSplitter.
       
  1164     if (qtRole == QAccessible::Grip) {
       
  1165         const QAInterface parent = interface.parent();
       
  1166         if (parent.isValid() && parent.role() == QAccessible::Splitter)
       
  1167             return CFStringRef(QAXSplitterRole);
       
  1168     }
       
  1169 
       
  1170     // Tab widgets and standalone tab bars get the kAXTabGroupRole. Accessibility
       
  1171     // for tab bars emebedded in a tab widget is handled by the tab widget.
       
  1172     if (isTabWidget(interface) || isStandaloneTabBar(interface))
       
  1173         return kAXTabGroupRole;
       
  1174 
       
  1175     if (QObject *object = interface.object()) {
       
  1176         // ### The interface for an abstract scroll area returns the generic "Client"
       
  1177         // role, so we have to to an extra detect on the QObject here.
       
  1178         if (object->inherits("QAbstractScrollArea") && interface.id() == 0)
       
  1179             return CFStringRef(QAXScrollAreaRole);
       
  1180 
       
  1181         if (object->inherits("QDockWidget"))
       
  1182             return CFStringRef(QAXUnknownRole);
       
  1183     }
       
  1184 
       
  1185     int i = 0;
       
  1186     int testRole = text_bindings[i][0].qt;
       
  1187     while (testRole != -1) {
       
  1188         if (testRole == qtRole)
       
  1189             return CFStringRef(text_bindings[i][0].mac);
       
  1190         ++i;
       
  1191         testRole = text_bindings[i][0].qt;
       
  1192     }
       
  1193 
       
  1194 //    qDebug() << "got unknown role!" << interface << interface.parent();
       
  1195 
       
  1196     return CFStringRef(QAXUnknownRole);
       
  1197 }
       
  1198 
       
  1199 /*
       
  1200     Translates a QAccessible::Role and an attribute name into a QAccessible::Text, taking into
       
  1201     account execptions listed in text_bindings.
       
  1202 */
       
  1203 #ifndef QT_MAC_USE_COCOA
       
  1204 static int textForRoleAndAttribute(QAccessible::Role role, CFStringRef attribute)
       
  1205 {
       
  1206      // Search for exception, return it if found.
       
  1207     int testRole = text_bindings[0][0].qt;
       
  1208     int i = 0;
       
  1209     while (testRole != -1) {
       
  1210         if (testRole == role) {
       
  1211             int j = 1;
       
  1212             int qtRole = text_bindings[i][j].qt;
       
  1213             CFStringRef testAttribute = CFStringRef(text_bindings[i][j].mac);
       
  1214             while (qtRole != -1) {
       
  1215                 if (CFStringCompare(attribute, testAttribute, 0) == kCFCompareEqualTo) {
       
  1216                     return (QAccessible::Text)qtRole;
       
  1217                 }
       
  1218                 ++j;
       
  1219                 testAttribute = CFStringRef(text_bindings[i][j].mac); /// ### custom compare
       
  1220                 qtRole = text_bindings[i][j].qt; /// ### custom compare
       
  1221             }
       
  1222             break;
       
  1223         }
       
  1224         ++i;
       
  1225         testRole = text_bindings[i][0].qt;
       
  1226     }
       
  1227 
       
  1228     // Return default mappping
       
  1229     if (CFStringCompare(attribute, CFStringRef(QAXTitleAttribute), 0) == kCFCompareEqualTo)
       
  1230         return QAccessible::Name;
       
  1231     else if (CFStringCompare(attribute, CFStringRef(QAXValueAttribute), 0) == kCFCompareEqualTo)
       
  1232         return QAccessible::Value;
       
  1233     else if (CFStringCompare(attribute, CFStringRef(QAXHelpAttribute), 0) == kCFCompareEqualTo)
       
  1234         return QAccessible::Help;
       
  1235     else if (CFStringCompare(attribute, CFStringRef(QAXDescriptionAttribute), 0) == kCFCompareEqualTo)
       
  1236         return QAccessible::Description;
       
  1237     else
       
  1238         return -1;
       
  1239 }
       
  1240 
       
  1241 /*
       
  1242     Returns the subrole string constant for the interface if it has one,
       
  1243     else returns an empty string.
       
  1244 */
       
  1245 static QCFString subrole(const QAInterface &interface)
       
  1246 {
       
  1247     const QAInterface parent = interface.parent();
       
  1248     if (parent.isValid() == false)
       
  1249         return QCFString();
       
  1250 
       
  1251     if (parent.role() == QAccessible::ScrollBar) {
       
  1252         QCFString subrole;
       
  1253         switch(interface.id()) {
       
  1254             case 1: subrole = CFStringRef(QAXDecrementArrowSubrole); break;
       
  1255             case 2: subrole = CFStringRef(QAXDecrementPageSubrole); break;
       
  1256             case 4: subrole = CFStringRef(QAXIncrementPageSubrole); break;
       
  1257             case 5: subrole = CFStringRef(QAXIncrementArrowSubrole); break;
       
  1258             default:
       
  1259             break;
       
  1260         }
       
  1261         return subrole;
       
  1262     }
       
  1263     return QCFString();
       
  1264 }
       
  1265 
       
  1266 // Gets the scroll bar orientation by asking the QAbstractSlider object directly.
       
  1267 static Qt::Orientation scrollBarOrientation(const QAInterface &scrollBar)
       
  1268 {
       
  1269     QObject *const object = scrollBar.object();
       
  1270     if (QAbstractSlider * const sliderObject = qobject_cast<QAbstractSlider * const>(object))
       
  1271         return sliderObject->orientation();
       
  1272 
       
  1273     return Qt::Vertical; // D'oh! The interface wasn't a scroll bar.
       
  1274 }
       
  1275 
       
  1276 static QAInterface scrollAreaGetScrollBarInterface(const QAInterface &scrollArea, Qt::Orientation orientation)
       
  1277 {
       
  1278     if (macRole(scrollArea) != CFStringRef(CFStringRef(QAXScrollAreaRole)))
       
  1279         return QAInterface();
       
  1280 
       
  1281     // Child 1 is the contents widget, 2 and 3 are the scroll bar containers wich contains possible scroll bars.
       
  1282     for (int i = 2; i <= 3; ++i) {
       
  1283         QAInterface scrollBarContainer = scrollArea.childAt(i);
       
  1284         for (int i = 1; i <= scrollBarContainer.childCount(); ++i) {
       
  1285             QAInterface scrollBar = scrollBarContainer.childAt(i);
       
  1286             if (scrollBar.isValid() &&
       
  1287                 scrollBar.role() == QAccessible::ScrollBar &&
       
  1288                 scrollBarOrientation(scrollBar) == orientation)
       
  1289                 return scrollBar;
       
  1290         }
       
  1291     }
       
  1292 
       
  1293     return QAInterface();
       
  1294 }
       
  1295 
       
  1296 static bool scrollAreaHasScrollBar(const QAInterface &scrollArea, Qt::Orientation orientation)
       
  1297 {
       
  1298     return scrollAreaGetScrollBarInterface(scrollArea, orientation).isValid();
       
  1299 }
       
  1300 
       
  1301 static QAElement scrollAreaGetScrollBar(const QAInterface &scrollArea, Qt::Orientation orientation)
       
  1302 {
       
  1303     return accessibleHierarchyManager()->lookup(scrollAreaGetScrollBarInterface(scrollArea, orientation));
       
  1304 }
       
  1305 
       
  1306 static QAElement scrollAreaGetContents(const QAInterface &scrollArea)
       
  1307 {
       
  1308     // Child 1 is the contents widget,
       
  1309     return accessibleHierarchyManager()->lookup(scrollArea.navigate(QAccessible::Child, 1));
       
  1310 }
       
  1311 
       
  1312 static QAElement tabWidgetGetContents(const QAInterface &interface)
       
  1313 {
       
  1314     // A kAXTabGroup has a kAXContents attribute, which consists of the
       
  1315     // ui elements for the current tab page. Get the current tab page
       
  1316     // from the QStackedWidget, where the current visible page can
       
  1317     // be found at index 1.
       
  1318     QAInterface stackedWidget = interface.childAt(1);
       
  1319     accessibleHierarchyManager()->registerChildren(stackedWidget);
       
  1320     QAInterface tabPageInterface = stackedWidget.childAt(1);
       
  1321     return accessibleHierarchyManager()->lookup(tabPageInterface);
       
  1322 }
       
  1323 
       
  1324 static QList<QAElement> tabBarGetTabs(const QAInterface &interface)
       
  1325 {
       
  1326     // Get the tabs by searching for children with the "PageTab" role.
       
  1327     // This filters out the left/right navigation buttons.
       
  1328     accessibleHierarchyManager()->registerChildren(interface);
       
  1329     QList<QAElement> tabs;
       
  1330     const int numChildren = interface.childCount();
       
  1331     for (int i = 1; i < numChildren + 1; ++i) {
       
  1332         QAInterface child = interface.navigate(QAccessible::Child, i);
       
  1333         if (child.isValid() && child.role() == QAccessible::PageTab) {
       
  1334             tabs.append(accessibleHierarchyManager()->lookup(child));
       
  1335         }
       
  1336     }
       
  1337     return tabs;
       
  1338 }
       
  1339 
       
  1340 static QList<QAElement> tabWidgetGetTabs(const QAInterface &interface)
       
  1341 {
       
  1342     // Each QTabWidget has two children, a QStackedWidget and a QTabBar.
       
  1343     // Get the tabs from the QTabBar.
       
  1344     return tabBarGetTabs(interface.childAt(2));
       
  1345 }
       
  1346 
       
  1347 static QList<QAElement> tabWidgetGetChildren(const QAInterface &interface)
       
  1348 {
       
  1349     // The children for a kAXTabGroup should consist of the tabs and the
       
  1350     // contents of the current open tab page.
       
  1351     QList<QAElement> children = tabWidgetGetTabs(interface);
       
  1352     children += tabWidgetGetContents(interface);
       
  1353     return children;
       
  1354 }
       
  1355 #endif //QT_MAC_USE_COCOA
       
  1356 
       
  1357 /*
       
  1358     Returns the label (buddy) interface for interface, or 0 if it has none.
       
  1359 */
       
  1360 /*
       
  1361 static QAInterface findLabel(const QAInterface &interface)
       
  1362 {
       
  1363     return interface.navigate(QAccessible::Label, 1);
       
  1364 }
       
  1365 */
       
  1366 /*
       
  1367     Returns a list of interfaces this interface labels, or an empty list if it doesn't label any.
       
  1368 */
       
  1369 /*
       
  1370 static QList<QAInterface> findLabelled(const QAInterface &interface)
       
  1371 {
       
  1372     QList<QAInterface> interfaceList;
       
  1373 
       
  1374     int count = 1;
       
  1375     const QAInterface labelled = interface.navigate(QAccessible::Labelled, count);
       
  1376     while (labelled.isValid()) {
       
  1377         interfaceList.append(labelled);
       
  1378         ++count;
       
  1379     }
       
  1380     return interfaceList;
       
  1381 }
       
  1382 */
       
  1383 /*
       
  1384     Tests if the given QAInterface has data for a mac attribute.
       
  1385 */
       
  1386 #ifndef QT_MAC_USE_COCOA
       
  1387 static bool supportsAttribute(CFStringRef attribute, const QAInterface &interface)
       
  1388 {
       
  1389     const int text = textForRoleAndAttribute(interface.role(), attribute);
       
  1390 
       
  1391     // Special case: Static texts don't have a title.
       
  1392     if (interface.role() == QAccessible::StaticText && attribute == CFStringRef(QAXTitleAttribute))
       
  1393         return false;
       
  1394 
       
  1395     // Return true if we the attribute matched a QAccessible::Role and we get text for that role from the interface.
       
  1396     if (text != -1) {
       
  1397         if (text == QAccessible::Value) // Special case for Value, see getValue()
       
  1398             return !getValue(interface).isEmpty();
       
  1399         else
       
  1400             return !interface.text((QAccessible::Text)text).isEmpty();
       
  1401     }
       
  1402 
       
  1403     if (CFStringCompare(attribute, CFStringRef(QAXChildrenAttribute),  0) == kCFCompareEqualTo) {
       
  1404         if (interface.childCount() > 0)
       
  1405             return true;
       
  1406     }
       
  1407 
       
  1408     if (CFStringCompare(attribute, CFStringRef(QAXSubroleAttribute),  0) == kCFCompareEqualTo) {
       
  1409         return (subrole(interface) != QCFString());
       
  1410     }
       
  1411 
       
  1412     return false;
       
  1413 }
       
  1414 
       
  1415 static void appendIfSupported(CFMutableArrayRef array, CFStringRef attribute, const QAInterface &interface)
       
  1416 {
       
  1417     if (supportsAttribute(attribute, interface))
       
  1418         qt_mac_append_cf_uniq(array, attribute);
       
  1419 }
       
  1420 
       
  1421 /*
       
  1422     Returns the names of the attributes the give QAInterface supports.
       
  1423 */
       
  1424 static OSStatus getAllAttributeNames(EventRef event, const QAInterface &interface, EventHandlerCallRef next_ref)
       
  1425 {
       
  1426     // Call system event handler.
       
  1427     OSStatus err = CallNextEventHandler(next_ref, event);
       
  1428     if(err != noErr && err != eventNotHandledErr)
       
  1429         return err;
       
  1430     CFMutableArrayRef attrs = 0;
       
  1431     GetEventParameter(event, kEventParamAccessibleAttributeNames, typeCFMutableArrayRef, 0,
       
  1432                       sizeof(attrs), 0, &attrs);
       
  1433 
       
  1434     if (!attrs)
       
  1435         return eventNotHandledErr;
       
  1436 
       
  1437     // Append attribute names that are always supported.
       
  1438     qt_mac_append_cf_uniq(attrs, CFStringRef(QAXPositionAttribute));
       
  1439     qt_mac_append_cf_uniq(attrs, CFStringRef(QAXSizeAttribute));
       
  1440     qt_mac_append_cf_uniq(attrs, CFStringRef(QAXRoleAttribute));
       
  1441     qt_mac_append_cf_uniq(attrs, CFStringRef(QAXEnabledAttribute));
       
  1442     qt_mac_append_cf_uniq(attrs, CFStringRef(QAXWindowAttribute));
       
  1443     qt_mac_append_cf_uniq(attrs, CFStringRef(QAXTopLevelUIElementAttribute));
       
  1444 
       
  1445     // Append these names if the QInterafceItem returns any data for them.
       
  1446     appendIfSupported(attrs, CFStringRef(QAXTitleAttribute), interface);
       
  1447     appendIfSupported(attrs, CFStringRef(QAXValueAttribute), interface);
       
  1448     appendIfSupported(attrs, CFStringRef(QAXDescriptionAttribute), interface);
       
  1449     appendIfSupported(attrs, CFStringRef(QAXLinkedUIElementsAttribute), interface);
       
  1450     appendIfSupported(attrs, CFStringRef(QAXHelpAttribute), interface);
       
  1451     appendIfSupported(attrs, CFStringRef(QAXTitleUIElementAttribute), interface);
       
  1452     appendIfSupported(attrs, CFStringRef(QAXChildrenAttribute), interface);
       
  1453     appendIfSupported(attrs, CFStringRef(QAXSubroleAttribute), interface);
       
  1454 
       
  1455     // Append attribute names based on the interaface role.
       
  1456     switch (interface.role())  {
       
  1457         case QAccessible::Window:
       
  1458             qt_mac_append_cf_uniq(attrs, CFStringRef(QAXMainAttribute));
       
  1459             qt_mac_append_cf_uniq(attrs, CFStringRef(QAXMinimizedAttribute));
       
  1460             qt_mac_append_cf_uniq(attrs, CFStringRef(QAXCloseButtonAttribute));
       
  1461             qt_mac_append_cf_uniq(attrs, CFStringRef(QAXZoomButtonAttribute));
       
  1462             qt_mac_append_cf_uniq(attrs, CFStringRef(QAXMinimizeButtonAttribute));
       
  1463             qt_mac_append_cf_uniq(attrs, CFStringRef(QAXToolbarButtonAttribute));
       
  1464             qt_mac_append_cf_uniq(attrs, CFStringRef(QAXGrowAreaAttribute));
       
  1465         break;
       
  1466         case QAccessible::RadioButton:
       
  1467         case QAccessible::CheckBox:
       
  1468             qt_mac_append_cf_uniq(attrs, CFStringRef(QAXMinValueAttribute));
       
  1469             qt_mac_append_cf_uniq(attrs, CFStringRef(QAXMaxValueAttribute));
       
  1470         break;
       
  1471         case QAccessible::ScrollBar:
       
  1472             qt_mac_append_cf_uniq(attrs, CFStringRef(QAXOrientationAttribute));
       
  1473         break;
       
  1474         case QAccessible::Splitter:
       
  1475             qt_mac_append_cf_uniq(attrs, CFStringRef(QAXSplittersAttribute));
       
  1476         break;
       
  1477         case QAccessible::Table:
       
  1478             qt_mac_append_cf_uniq(attrs, CFStringRef(QAXRowsAttribute));
       
  1479             qt_mac_append_cf_uniq(attrs, CFStringRef(QAXVisibleRowsAttribute));
       
  1480             qt_mac_append_cf_uniq(attrs, CFStringRef(QAXSelectedRowsAttribute));
       
  1481         break;
       
  1482         default:
       
  1483         break;
       
  1484     }
       
  1485 
       
  1486     // Append attribute names based on the mac accessibility role.
       
  1487     const QCFString mac_role = macRole(interface);
       
  1488     if (mac_role == CFStringRef(QAXSplitterRole)) {
       
  1489         qt_mac_append_cf_uniq(attrs, CFStringRef(QAXPreviousContentsAttribute));
       
  1490         qt_mac_append_cf_uniq(attrs, CFStringRef(QAXNextContentsAttribute));
       
  1491         qt_mac_append_cf_uniq(attrs, CFStringRef(QAXOrientationAttribute));
       
  1492     } else if (mac_role == CFStringRef(QAXScrollAreaRole)) {
       
  1493         if (scrollAreaHasScrollBar(interface, Qt::Horizontal))
       
  1494             qt_mac_append_cf_uniq(attrs, CFStringRef(QAXHorizontalScrollBarAttribute));
       
  1495         if (scrollAreaHasScrollBar(interface, Qt::Vertical))
       
  1496             qt_mac_append_cf_uniq(attrs, CFStringRef(QAXVerticalScrollBarAttribute));
       
  1497         qt_mac_append_cf_uniq(attrs, CFStringRef(QAXContentsAttribute));
       
  1498     } else if (mac_role == CFStringRef(QAXTabGroupRole)) {
       
  1499         qt_mac_append_cf_uniq(attrs, CFStringRef(QAXTabsAttribute));
       
  1500         // Only tab widgets can have the contents attribute, there is no way of getting
       
  1501         // the contents from a QTabBar.
       
  1502         if (isTabWidget(interface)) 
       
  1503             qt_mac_append_cf_uniq(attrs, CFStringRef(QAXContentsAttribute));
       
  1504     }
       
  1505 
       
  1506     return noErr;
       
  1507 }
       
  1508 
       
  1509 static void handleStringAttribute(EventRef event, QAccessible::Text text, const QAInterface &interface)
       
  1510 {
       
  1511     QString str = interface.text(text);
       
  1512     if (str.isEmpty())
       
  1513         return;
       
  1514 
       
  1515     // Remove any html markup from the text string, or VoiceOver will read the html tags.
       
  1516     static QTextDocument document;
       
  1517     document.setHtml(str);
       
  1518     str = document.toPlainText();
       
  1519 
       
  1520     CFStringRef cfstr = QCFString::toCFStringRef(str);
       
  1521     SetEventParameter(event, kEventParamAccessibleAttributeValue, typeCFStringRef, sizeof(cfstr), &cfstr);
       
  1522 }
       
  1523 
       
  1524 /*
       
  1525     Handles the parent attribute for a interface.
       
  1526     There are basically three cases here:
       
  1527     1. interface is a HIView and has only HIView children.
       
  1528     2. interface is a HIView but has children that is not a HIView
       
  1529     3. interface is not a HIView.
       
  1530 */
       
  1531 static OSStatus handleChildrenAttribute(EventHandlerCallRef next_ref, EventRef event, QAInterface &interface)
       
  1532 {
       
  1533    // Add the children for this interface to the global QAccessibelHierachyManager.
       
  1534     accessibleHierarchyManager()->registerChildren(interface);
       
  1535 
       
  1536     if (isTabWidget(interface)) {
       
  1537         QList<QAElement> children = tabWidgetGetChildren(interface);
       
  1538         const int childCount = children.count();
       
  1539 
       
  1540         CFMutableArrayRef array = 0;
       
  1541         array = CFArrayCreateMutable(0, 0, &kCFTypeArrayCallBacks);
       
  1542         for (int i = 0; i < childCount; ++i)  {
       
  1543             qt_mac_append_cf_uniq(array, children.at(i).element());
       
  1544         }
       
  1545 
       
  1546         OSStatus err;
       
  1547         err = SetEventParameter(event, kEventParamAccessibleAttributeValue, typeCFArrayRef, sizeof(array), &array);
       
  1548         if (err != noErr)
       
  1549             qWarning("Qt:Internal error (%s:%d)", __FILE__, __LINE__);
       
  1550 
       
  1551         return noErr;
       
  1552     }
       
  1553 
       
  1554     const QList<QAElement> children = lookup(interface.children());
       
  1555     const int childCount = children.count();
       
  1556 
       
  1557     OSStatus err = eventNotHandledErr;
       
  1558     if (interface.isHIView())
       
  1559         err = CallNextEventHandler(next_ref, event);
       
  1560 
       
  1561     CFMutableArrayRef array = 0;
       
  1562     int arraySize = 0;
       
  1563     if (err == noErr) {
       
  1564         CFTypeRef obj = 0;
       
  1565         err = GetEventParameter(event, kEventParamAccessibleAttributeValue, typeCFTypeRef, NULL , sizeof(obj), NULL, &obj);
       
  1566         if (err == noErr && obj != 0) {
       
  1567             array = (CFMutableArrayRef)obj;
       
  1568             arraySize = CFArrayGetCount(array);
       
  1569         }
       
  1570     }
       
  1571 
       
  1572     if (array) {
       
  1573         CFArrayRemoveAllValues(array);
       
  1574         for (int i = 0; i < childCount; ++i)  {
       
  1575             qt_mac_append_cf_uniq(array, children.at(i).element());
       
  1576         }
       
  1577     } else {
       
  1578         array = CFArrayCreateMutable(0, 0, &kCFTypeArrayCallBacks);
       
  1579         for (int i = 0; i < childCount; ++i)  {
       
  1580             qt_mac_append_cf_uniq(array, children.at(i).element());
       
  1581         }
       
  1582 
       
  1583         err = SetEventParameter(event, kEventParamAccessibleAttributeValue, typeCFArrayRef, sizeof(array), &array);
       
  1584         if (err != noErr)
       
  1585             qWarning("Qt:Internal error (%s:%d)", __FILE__, __LINE__);
       
  1586     }
       
  1587 
       
  1588     return noErr;
       
  1589 }
       
  1590 
       
  1591 /*
       
  1592 
       
  1593 */
       
  1594 static OSStatus handleParentAttribute(EventHandlerCallRef next_ref, EventRef event, const QAInterface &interface)
       
  1595 {
       
  1596     OSStatus err = eventNotHandledErr;
       
  1597     if (interface.isHIView()) {
       
  1598          err = CallNextEventHandler(next_ref, event);
       
  1599     }
       
  1600     if (err == noErr)
       
  1601         return err;
       
  1602 
       
  1603     const QAInterface parentInterface  = interface.navigate(QAccessible::Ancestor, 1);
       
  1604     const QAElement parentElement = accessibleHierarchyManager()->lookup(parentInterface);
       
  1605 
       
  1606     if (parentElement.isValid() == false)
       
  1607         return eventNotHandledErr;
       
  1608 
       
  1609     AXUIElementRef elementRef = parentElement.element();
       
  1610     SetEventParameter(event, kEventParamAccessibleAttributeValue, typeCFTypeRef, sizeof(elementRef), &elementRef);
       
  1611     return noErr;
       
  1612 }
       
  1613 #endif
       
  1614 
       
  1615 struct IsWindowTest
       
  1616 {
       
  1617     static inline bool test(const QAInterface &interface)
       
  1618     {
       
  1619         return (interface.role() == QAccessible::Window);
       
  1620     }
       
  1621 };
       
  1622 
       
  1623 struct IsWindowAndNotDrawerOrSheetTest
       
  1624 {
       
  1625     static inline bool test(const QAInterface &interface)
       
  1626     {
       
  1627         QWidget * const widget = qobject_cast<QWidget*>(interface.object());
       
  1628         return (interface.role() == QAccessible::Window &&
       
  1629                 widget && widget->isWindow() &&
       
  1630                 !qt_mac_is_macdrawer(widget) &&
       
  1631                 !qt_mac_is_macsheet(widget));
       
  1632     }
       
  1633 };
       
  1634 
       
  1635 /*
       
  1636     Navigates up the iterfaces ancestor hierachy until a QAccessibleInterface that
       
  1637     passes the Test is found. If we reach a interface that is a HIView we stop the
       
  1638     search and call AXUIElementCopyAttributeValue.
       
  1639 */
       
  1640 template <typename TestType>
       
  1641 OSStatus navigateAncestors(EventHandlerCallRef next_ref, EventRef event, const QAInterface &interface, CFStringRef attribute)
       
  1642 {
       
  1643     if (interface.isHIView())
       
  1644         return CallNextEventHandler(next_ref, event);
       
  1645 
       
  1646     QAInterface current = interface;
       
  1647     QAElement element;
       
  1648     while (current.isValid()) {
       
  1649         if (TestType::test(interface)) {
       
  1650             element = accessibleHierarchyManager()->lookup(current);
       
  1651             break;
       
  1652         }
       
  1653 
       
  1654         // If we reach an InterfaceItem that is a HiView we can hand of the search to
       
  1655         // the system event handler. This is the common case.
       
  1656         if (current.isHIView()) {
       
  1657             CFTypeRef value = 0;
       
  1658             const QAElement currentElement = accessibleHierarchyManager()->lookup(current);
       
  1659             AXError err = AXUIElementCopyAttributeValue(currentElement.element(), attribute, &value);
       
  1660             AXUIElementRef newElement = (AXUIElementRef)value;
       
  1661 
       
  1662             if (err == noErr)
       
  1663                 element = QAElement(newElement);
       
  1664 
       
  1665             if (newElement != 0)
       
  1666                 CFRelease(newElement);
       
  1667             break;
       
  1668         }
       
  1669 
       
  1670         QAInterface next = current.parent();
       
  1671         if (next.isValid() == false)
       
  1672             break;
       
  1673         if (next == current)
       
  1674             break;
       
  1675         current = next;
       
  1676     }
       
  1677 
       
  1678     if (element.isValid() == false)
       
  1679         return eventNotHandledErr;
       
  1680 
       
  1681 
       
  1682     AXUIElementRef elementRef = element.element();
       
  1683     SetEventParameter(event, kEventParamAccessibleAttributeValue, typeCFTypeRef,
       
  1684                                       sizeof(elementRef), &elementRef);
       
  1685     return noErr;
       
  1686 }
       
  1687 
       
  1688 /*
       
  1689     Returns the top-level window for an interface, which is the closest ancestor interface that
       
  1690     has the Window role, but is not a sheet or a drawer.
       
  1691 */
       
  1692 #ifndef QT_MAC_USE_COCOA
       
  1693 static OSStatus handleWindowAttribute(EventHandlerCallRef next_ref, EventRef event, const QAInterface &interface)
       
  1694 {
       
  1695     return navigateAncestors<IsWindowAndNotDrawerOrSheetTest>(next_ref, event, interface, CFStringRef(QAXWindowAttribute));
       
  1696 }
       
  1697 
       
  1698 /*
       
  1699     Returns the top-level window for an interface, which is the closest ancestor interface that
       
  1700     has the Window role. (Can also be a sheet or a drawer)
       
  1701 */
       
  1702 static OSStatus handleTopLevelUIElementAttribute(EventHandlerCallRef next_ref, EventRef event, const QAInterface &interface)
       
  1703 {
       
  1704     return navigateAncestors<IsWindowTest>(next_ref, event, interface, CFStringRef(QAXTopLevelUIElementAttribute));
       
  1705 }
       
  1706 
       
  1707 /*
       
  1708     Returns the tab buttons for an interface.
       
  1709 */
       
  1710 static OSStatus handleTabsAttribute(EventHandlerCallRef next_ref, EventRef event, QAInterface &interface)
       
  1711 {
       
  1712     Q_UNUSED(next_ref);
       
  1713     if (isTabWidget(interface))
       
  1714         return setAttributeValue(event, tabWidgetGetTabs(interface));
       
  1715     else
       
  1716         return setAttributeValue(event, tabBarGetTabs(interface));
       
  1717 }
       
  1718 
       
  1719 static OSStatus handlePositionAttribute(EventHandlerCallRef, EventRef event, const QAInterface &interface)
       
  1720 {
       
  1721     QPoint qpoint(interface.rect().topLeft());
       
  1722     HIPoint point;
       
  1723     point.x = qpoint.x();
       
  1724     point.y = qpoint.y();
       
  1725     SetEventParameter(event, kEventParamAccessibleAttributeValue, typeHIPoint, sizeof(point), &point);
       
  1726     return noErr;
       
  1727 }
       
  1728 
       
  1729 static OSStatus handleSizeAttribute(EventHandlerCallRef, EventRef event, const QAInterface &interface)
       
  1730 {
       
  1731     QSize qSize(interface.rect().size());
       
  1732     HISize size;
       
  1733     size.width = qSize.width();
       
  1734     size.height = qSize.height();
       
  1735     SetEventParameter(event, kEventParamAccessibleAttributeValue, typeHISize, sizeof(size), &size);
       
  1736     return noErr;
       
  1737 }
       
  1738 
       
  1739 static OSStatus handleSubroleAttribute(EventHandlerCallRef, EventRef event, const QAInterface &interface)
       
  1740 {
       
  1741     const QCFString role = subrole(interface);
       
  1742     CFStringRef rolestr = (CFStringRef)role;
       
  1743     SetEventParameter(event, kEventParamAccessibleAttributeValue, typeCFTypeRef, sizeof(rolestr), &rolestr);
       
  1744     return noErr;
       
  1745 }
       
  1746 
       
  1747 static OSStatus handleOrientationAttribute(EventHandlerCallRef next_ref, EventRef event, const QAInterface &interface)
       
  1748 {
       
  1749     QObject *const object = interface.object();
       
  1750     Qt::Orientation orientation;
       
  1751     if (interface.role() == QAccessible::ScrollBar) {
       
  1752         orientation  = scrollBarOrientation(interface);
       
  1753     } else if (QSplitterHandle * const splitter = qobject_cast<QSplitterHandle * const>(object)) {
       
  1754         // Qt reports the layout orientation, but we want the splitter handle orientation.
       
  1755         orientation = (splitter->orientation() == Qt::Horizontal) ? Qt::Vertical : Qt::Horizontal;
       
  1756     } else {
       
  1757         return CallNextEventHandler(next_ref, event);
       
  1758     }
       
  1759     const CFStringRef orientationString = (orientation == Qt::Vertical)
       
  1760         ? CFStringRef(QAXVerticalOrientationValue) : CFStringRef(QAXHorizontalOrientationValue);
       
  1761     SetEventParameter(event, kEventParamAccessibleAttributeValue, typeCFStringRef, sizeof(orientationString), &orientationString);
       
  1762     return noErr;
       
  1763 }
       
  1764 
       
  1765 /*
       
  1766     Figures out the next or previous contents for a splitter.
       
  1767 */
       
  1768 static OSStatus handleSplitterContentsAttribute(EventHandlerCallRef next_ref, EventRef event, const QAInterface &interface, QCFString nextOrPrev)
       
  1769 {
       
  1770     if (interface.isValid() == false || interface.role() != QAccessible::Grip)
       
  1771         return eventNotHandledErr;
       
  1772 
       
  1773     const QAInterface parent = interface.parent();
       
  1774     if (parent.isValid() == false)
       
  1775         return CallNextEventHandler(next_ref, event);
       
  1776 
       
  1777     if (parent.role() != QAccessible::Splitter)
       
  1778         return CallNextEventHandler(next_ref, event);
       
  1779 
       
  1780     const QSplitter * const splitter = qobject_cast<const QSplitter * const>(parent.object());
       
  1781     if (splitter == 0)
       
  1782         return CallNextEventHandler(next_ref, event);
       
  1783 
       
  1784     QWidget * const splitterHandle = qobject_cast<QWidget * const>(interface.object());
       
  1785     const int splitterHandleIndex = splitter->indexOf(splitterHandle);
       
  1786     const int widgetIndex = (nextOrPrev == QCFString(CFStringRef(QAXPreviousContentsAttribute))) ? splitterHandleIndex - 1 : splitterHandleIndex;
       
  1787     const QAElement contentsElement = accessibleHierarchyManager()->lookup(splitter->widget(widgetIndex), 0);
       
  1788     return setAttributeValue(event, QList<QAElement>() << contentsElement);
       
  1789 }
       
  1790 
       
  1791 /*
       
  1792     Creates a list of all splitter handles the splitter contains.
       
  1793 */
       
  1794 static OSStatus handleSplittersAttribute(EventHandlerCallRef next_ref, EventRef event, QAInterface &interface)
       
  1795 {
       
  1796     const QSplitter * const splitter = qobject_cast<const QSplitter * const>(interface.object());
       
  1797     if (splitter == 0)
       
  1798         return CallNextEventHandler(next_ref, event);
       
  1799 
       
  1800     accessibleHierarchyManager()->registerChildren(interface);
       
  1801 
       
  1802     QList<QAElement> handles;
       
  1803     const int visibleSplitterCount = splitter->count() -1; // skip first handle, it's always invisible.
       
  1804     for (int i = 0; i < visibleSplitterCount; ++i)
       
  1805         handles.append(accessibleHierarchyManager()->lookup(splitter->handle(i + 1), 0));
       
  1806 
       
  1807     return setAttributeValue(event, handles);
       
  1808 }
       
  1809 
       
  1810 // This handler gets the scroll bars for a scroll area
       
  1811 static OSStatus handleScrollBarAttribute(EventHandlerCallRef next_ref, EventRef event, QAInterface &scrollArea, Qt::Orientation orientation)
       
  1812 {
       
  1813     QAElement scrollBar = scrollAreaGetScrollBar(scrollArea, orientation);
       
  1814     if (scrollBar.isValid() == false)
       
  1815         return CallNextEventHandler(next_ref, event);
       
  1816 
       
  1817     AXUIElementRef elementRef = scrollBar.element();
       
  1818     SetEventParameter(event, kEventParamAccessibleAttributeValue, typeCFTypeRef, sizeof(elementRef), &elementRef);
       
  1819     return noErr;
       
  1820 }
       
  1821 
       
  1822 // This handler gets the contents for a scroll area or tab widget.
       
  1823 static OSStatus handleContentsAttribute(EventHandlerCallRef next_ref, EventRef event, QAInterface &interface)
       
  1824 {
       
  1825     const QCFString mac_role = macRole(interface);
       
  1826 
       
  1827     QAElement contents;
       
  1828 
       
  1829     if (mac_role == kAXTabGroupRole) {
       
  1830         contents = tabWidgetGetContents(interface);
       
  1831     } else {
       
  1832         contents = scrollAreaGetContents(interface);
       
  1833         if (contents.isValid() == false)
       
  1834             return CallNextEventHandler(next_ref, event);
       
  1835     }
       
  1836 
       
  1837     return setAttributeValue(event, QList<QAElement>() << contents);
       
  1838 }
       
  1839 
       
  1840 static OSStatus handleRowsAttribute(EventHandlerCallRef, EventRef event, QAInterface &tableView)
       
  1841 {
       
  1842     QList<QAElement> rows = lookup(tableView.children());
       
  1843 
       
  1844     // kill the first row which is the horizontal header.
       
  1845     rows.removeAt(0);
       
  1846 
       
  1847     return setAttributeValue(event, rows);
       
  1848 }
       
  1849 
       
  1850 static OSStatus handleVisibleRowsAttribute(EventHandlerCallRef, EventRef event, QAInterface &tableView)
       
  1851 {
       
  1852     QList<QAElement> visibleRows;
       
  1853 
       
  1854     QList<QAInterface> rows = tableView.children();
       
  1855     // kill the first row which is the horizontal header.
       
  1856     rows.removeAt(0);
       
  1857 
       
  1858     foreach (const QAInterface &interface, rows)
       
  1859         if ((interface.state() & QAccessible::Invisible) == false)
       
  1860             visibleRows.append(accessibleHierarchyManager()->lookup(interface));
       
  1861 
       
  1862     return setAttributeValue(event, visibleRows);
       
  1863 }
       
  1864 
       
  1865 static OSStatus handleSelectedRowsAttribute(EventHandlerCallRef, EventRef event, QAInterface &tableView)
       
  1866 {
       
  1867     QList<QAElement> selectedRows;
       
  1868     foreach (const QAInterface &interface, tableView.children())
       
  1869         if ((interface.state() & QAccessible::Selected))
       
  1870             selectedRows.append(accessibleHierarchyManager()->lookup(interface));
       
  1871 
       
  1872     return setAttributeValue(event, selectedRows);
       
  1873 }
       
  1874 
       
  1875 static OSStatus getNamedAttribute(EventHandlerCallRef next_ref, EventRef event, QAInterface &interface)
       
  1876 {
       
  1877     CFStringRef var;
       
  1878     GetEventParameter(event, kEventParamAccessibleAttributeName, typeCFStringRef, 0,
       
  1879                               sizeof(var), 0, &var);
       
  1880 
       
  1881     if (CFStringCompare(var, CFStringRef(QAXChildrenAttribute), 0) == kCFCompareEqualTo) {
       
  1882         return handleChildrenAttribute(next_ref, event, interface);
       
  1883     } else if(CFStringCompare(var, CFStringRef(QAXTopLevelUIElementAttribute), 0) == kCFCompareEqualTo) {
       
  1884         return handleTopLevelUIElementAttribute(next_ref, event, interface);
       
  1885     } else if(CFStringCompare(var, CFStringRef(QAXWindowAttribute), 0) == kCFCompareEqualTo) {
       
  1886         return handleWindowAttribute(next_ref, event, interface);
       
  1887     } else if(CFStringCompare(var, CFStringRef(QAXParentAttribute), 0) == kCFCompareEqualTo) {
       
  1888         return handleParentAttribute(next_ref, event, interface);
       
  1889     } else if (CFStringCompare(var, CFStringRef(QAXPositionAttribute), 0) == kCFCompareEqualTo) {
       
  1890         return handlePositionAttribute(next_ref, event, interface);
       
  1891     } else if (CFStringCompare(var, CFStringRef(QAXSizeAttribute), 0) == kCFCompareEqualTo) {
       
  1892         return handleSizeAttribute(next_ref, event, interface);
       
  1893     } else  if (CFStringCompare(var, CFStringRef(QAXRoleAttribute), 0) == kCFCompareEqualTo) {
       
  1894         CFStringRef role = macRole(interface);
       
  1895 // ###
       
  1896 //        QWidget * const widget = qobject_cast<QWidget *>(interface.object());
       
  1897 //        if (role == CFStringRef(QAXUnknownRole) && widget && widget->isWindow())
       
  1898 //            role = CFStringRef(QAXWindowRole);
       
  1899 
       
  1900         SetEventParameter(event, kEventParamAccessibleAttributeValue, typeCFStringRef,
       
  1901                           sizeof(role), &role);
       
  1902 
       
  1903     } else if (CFStringCompare(var, CFStringRef(QAXEnabledAttribute), 0) == kCFCompareEqualTo) {
       
  1904         Boolean val =  !((interface.state() & QAccessible::Unavailable))
       
  1905                      && !((interface.state() & QAccessible::Invisible));
       
  1906         SetEventParameter(event, kEventParamAccessibleAttributeValue, typeBoolean,
       
  1907                           sizeof(val), &val);
       
  1908     } else if (CFStringCompare(var, CFStringRef(QAXExpandedAttribute), 0) == kCFCompareEqualTo) {
       
  1909         Boolean val = (interface.state() & QAccessible::Expanded);
       
  1910         SetEventParameter(event, kEventParamAccessibleAttributeValue, typeBoolean,
       
  1911                           sizeof(val), &val);
       
  1912     } else if (CFStringCompare(var, CFStringRef(QAXSelectedAttribute), 0) == kCFCompareEqualTo) {
       
  1913         Boolean val = (interface.state() & QAccessible::Selection);
       
  1914         SetEventParameter(event, kEventParamAccessibleAttributeValue, typeBoolean,
       
  1915                           sizeof(val), &val);
       
  1916     } else if (CFStringCompare(var, CFStringRef(QAXFocusedAttribute), 0) == kCFCompareEqualTo) {
       
  1917         Boolean val = (interface.state() & QAccessible::Focus);
       
  1918         SetEventParameter(event, kEventParamAccessibleAttributeValue, typeBoolean,
       
  1919                           sizeof(val), &val);
       
  1920     } else if (CFStringCompare(var, CFStringRef(QAXSelectedChildrenAttribute), 0) == kCFCompareEqualTo) {
       
  1921         const int cc = interface.childCount();
       
  1922         QList<QAElement> selected;
       
  1923         for (int i = 1; i <= cc; ++i) {
       
  1924             const QAInterface child_iface = interface.navigate(QAccessible::Child, i);
       
  1925             if (child_iface.isValid() && child_iface.state() & QAccessible::Selected)
       
  1926                 selected.append(accessibleHierarchyManager()->lookup(child_iface));
       
  1927         }
       
  1928 
       
  1929         return setAttributeValue(event, selected);
       
  1930 
       
  1931       } else if (CFStringCompare(var, CFStringRef(QAXCloseButtonAttribute), 0) == kCFCompareEqualTo) {
       
  1932         if(interface.object() && interface.object()->isWidgetType()) {
       
  1933             Boolean val = true; //do we want to add a WState for this?
       
  1934             SetEventParameter(event, kEventParamAccessibleAttributeValue, typeBoolean,
       
  1935                               sizeof(val), &val);
       
  1936         }
       
  1937     } else if (CFStringCompare(var, CFStringRef(QAXZoomButtonAttribute), 0) == kCFCompareEqualTo) {
       
  1938         if(interface.object() && interface.object()->isWidgetType()) {
       
  1939             QWidget *widget = (QWidget*)interface.object();
       
  1940             Boolean val = (widget->windowFlags() & Qt::WindowMaximizeButtonHint);
       
  1941             SetEventParameter(event, kEventParamAccessibleAttributeValue, typeBoolean,
       
  1942                               sizeof(val), &val);
       
  1943         }
       
  1944     } else if (CFStringCompare(var, CFStringRef(QAXMinimizeButtonAttribute), 0) == kCFCompareEqualTo) {
       
  1945         if(interface.object() && interface.object()->isWidgetType()) {
       
  1946             QWidget *widget = (QWidget*)interface.object();
       
  1947             Boolean val = (widget->windowFlags() & Qt::WindowMinimizeButtonHint);
       
  1948             SetEventParameter(event, kEventParamAccessibleAttributeValue, typeBoolean,
       
  1949                               sizeof(val), &val);
       
  1950         }
       
  1951     } else if (CFStringCompare(var, CFStringRef(QAXToolbarButtonAttribute), 0) == kCFCompareEqualTo) {
       
  1952         if(interface.object() && interface.object()->isWidgetType()) {
       
  1953             QWidget *widget = (QWidget*)interface.object();
       
  1954             Boolean val = qobject_cast<QMainWindow *>(widget) != 0;
       
  1955             SetEventParameter(event, kEventParamAccessibleAttributeValue, typeBoolean,
       
  1956                               sizeof(val), &val);
       
  1957         }
       
  1958     } else if (CFStringCompare(var, CFStringRef(QAXGrowAreaAttribute), 0) == kCFCompareEqualTo) {
       
  1959         if(interface.object() && interface.object()->isWidgetType()) {
       
  1960             Boolean val = true; //do we want to add a WState for this?
       
  1961             SetEventParameter(event, kEventParamAccessibleAttributeValue, typeBoolean,
       
  1962                               sizeof(val), &val);
       
  1963         }
       
  1964     } else if (CFStringCompare(var, CFStringRef(QAXMinimizedAttribute), 0) == kCFCompareEqualTo) {
       
  1965         if (interface.object() && interface.object()->isWidgetType()) {
       
  1966             QWidget *widget = (QWidget*)interface.object();
       
  1967             Boolean val = (widget->windowState() & Qt::WindowMinimized);
       
  1968             SetEventParameter(event, kEventParamAccessibleAttributeValue, typeBoolean,
       
  1969                               sizeof(val), &val);
       
  1970         }
       
  1971     } else if (CFStringCompare(var, CFStringRef(QAXSubroleAttribute), 0) == kCFCompareEqualTo) {
       
  1972         return handleSubroleAttribute(next_ref, event, interface);
       
  1973     } else if (CFStringCompare(var, CFStringRef(QAXRoleDescriptionAttribute), 0) == kCFCompareEqualTo) {
       
  1974 #if !defined(QT_MAC_USE_COCOA)
       
  1975         if (HICopyAccessibilityRoleDescription) {
       
  1976             const CFStringRef roleDescription = HICopyAccessibilityRoleDescription(macRole(interface), 0);
       
  1977             SetEventParameter(event, kEventParamAccessibleAttributeValue, typeCFStringRef,
       
  1978                           sizeof(roleDescription), &roleDescription);
       
  1979         } else
       
  1980 #endif
       
  1981         {
       
  1982             // Just use Qt::Description on 10.3
       
  1983             handleStringAttribute(event, QAccessible::Description, interface);
       
  1984         }
       
  1985     } else if (CFStringCompare(var, CFStringRef(QAXTitleAttribute), 0) == kCFCompareEqualTo) {
       
  1986         const QAccessible::Role role = interface.role();
       
  1987         const QAccessible::Text text = (QAccessible::Text)textForRoleAndAttribute(role, var);
       
  1988         handleStringAttribute(event, text, interface);
       
  1989     } else if (CFStringCompare(var, CFStringRef(QAXValueAttribute), 0) == kCFCompareEqualTo) {
       
  1990         const QAccessible::Role role = interface.role();
       
  1991         const QAccessible::Text text = (QAccessible::Text)textForRoleAndAttribute(role, var);
       
  1992         if (role == QAccessible::CheckBox || role == QAccessible::RadioButton) {
       
  1993             int value = buttonValue(interface);
       
  1994             SetEventParameter(event, kEventParamAccessibleAttributeValue, typeUInt32, sizeof(value), &value);
       
  1995         } else {
       
  1996             handleStringAttribute(event, text, interface);
       
  1997         }
       
  1998     } else if (CFStringCompare(var, CFStringRef(QAXDescriptionAttribute), 0) == kCFCompareEqualTo) {
       
  1999         const QAccessible::Role role = interface.role();
       
  2000         const QAccessible::Text text = (QAccessible::Text)textForRoleAndAttribute(role, var);
       
  2001         handleStringAttribute(event, text, interface);
       
  2002     } else if (CFStringCompare(var, CFStringRef(QAXLinkedUIElementsAttribute), 0) == kCFCompareEqualTo) {
       
  2003         return CallNextEventHandler(next_ref, event);
       
  2004     } else if (CFStringCompare(var, CFStringRef(QAXHelpAttribute), 0) == kCFCompareEqualTo) {
       
  2005         const QAccessible::Role role = interface.role();
       
  2006         const QAccessible::Text text = (QAccessible::Text)textForRoleAndAttribute(role, var);
       
  2007         handleStringAttribute(event, text, interface);
       
  2008     } else if (CFStringCompare(var, kAXTitleUIElementAttribute, 0) == kCFCompareEqualTo) {
       
  2009         return CallNextEventHandler(next_ref, event);
       
  2010     } else if (CFStringCompare(var, CFStringRef(QAXTabsAttribute), 0) == kCFCompareEqualTo) {
       
  2011         return handleTabsAttribute(next_ref, event, interface);
       
  2012     } else if (CFStringCompare(var, CFStringRef(QAXMinValueAttribute), 0) == kCFCompareEqualTo) {
       
  2013         // tabs we first go to the tab bar which is child #2.
       
  2014         QAInterface tabBarInterface = interface.childAt(2);
       
  2015         return handleTabsAttribute(next_ref, event, tabBarInterface);
       
  2016     } else if (CFStringCompare(var, CFStringRef(QAXMinValueAttribute), 0) == kCFCompareEqualTo) {
       
  2017         if (interface.role() == QAccessible::RadioButton || interface.role() == QAccessible::CheckBox) {
       
  2018             uint value = 0;
       
  2019             SetEventParameter(event, kEventParamAccessibleAttributeValue, typeUInt32, sizeof(value), &value);
       
  2020         } else {
       
  2021             return CallNextEventHandler(next_ref, event);
       
  2022         }
       
  2023     } else if (CFStringCompare(var, CFStringRef(QAXMaxValueAttribute), 0) == kCFCompareEqualTo) {
       
  2024         if (interface.role() == QAccessible::RadioButton || interface.role() == QAccessible::CheckBox) {
       
  2025             uint value = 2;
       
  2026             SetEventParameter(event, kEventParamAccessibleAttributeValue, typeUInt32, sizeof(value), &value);
       
  2027         } else {
       
  2028             return CallNextEventHandler(next_ref, event);
       
  2029         }
       
  2030     } else if (CFStringCompare(var, CFStringRef(QAXOrientationAttribute), 0) == kCFCompareEqualTo) {
       
  2031         return handleOrientationAttribute(next_ref, event, interface);
       
  2032     } else if (CFStringCompare(var, CFStringRef(QAXPreviousContentsAttribute), 0) == kCFCompareEqualTo) {
       
  2033         return handleSplitterContentsAttribute(next_ref, event, interface, CFStringRef(QAXPreviousContentsAttribute));
       
  2034     } else if (CFStringCompare(var, CFStringRef(QAXNextContentsAttribute), 0) == kCFCompareEqualTo) {
       
  2035         return handleSplitterContentsAttribute(next_ref, event, interface, CFStringRef(QAXNextContentsAttribute));
       
  2036     } else if (CFStringCompare(var, CFStringRef(QAXSplittersAttribute), 0) == kCFCompareEqualTo) {
       
  2037         return handleSplittersAttribute(next_ref, event, interface);
       
  2038     } else if (CFStringCompare(var, CFStringRef(QAXHorizontalScrollBarAttribute), 0) == kCFCompareEqualTo) {
       
  2039         return handleScrollBarAttribute(next_ref, event, interface, Qt::Horizontal);
       
  2040     } else if (CFStringCompare(var, CFStringRef(QAXVerticalScrollBarAttribute), 0) == kCFCompareEqualTo) {
       
  2041         return handleScrollBarAttribute(next_ref, event, interface, Qt::Vertical);
       
  2042     } else if (CFStringCompare(var, CFStringRef(QAXContentsAttribute), 0) == kCFCompareEqualTo) {
       
  2043         return handleContentsAttribute(next_ref, event, interface);
       
  2044     } else if (CFStringCompare(var, CFStringRef(QAXRowsAttribute), 0) == kCFCompareEqualTo) {
       
  2045         return handleRowsAttribute(next_ref, event, interface);
       
  2046     } else if (CFStringCompare(var, CFStringRef(QAXVisibleRowsAttribute), 0) == kCFCompareEqualTo) {
       
  2047         return handleVisibleRowsAttribute(next_ref, event, interface);
       
  2048     } else if (CFStringCompare(var, CFStringRef(QAXSelectedRowsAttribute), 0) == kCFCompareEqualTo) {
       
  2049         return handleSelectedRowsAttribute(next_ref, event, interface);
       
  2050     } else {
       
  2051         return CallNextEventHandler(next_ref, event);
       
  2052     }
       
  2053     return noErr;
       
  2054 }
       
  2055 
       
  2056 static OSStatus isNamedAttributeSettable(EventRef event, const QAInterface &interface)
       
  2057 {
       
  2058     CFStringRef var;
       
  2059     GetEventParameter(event, kEventParamAccessibleAttributeName, typeCFStringRef, 0,
       
  2060                       sizeof(var), 0, &var);
       
  2061     Boolean settable = false;
       
  2062     if (CFStringCompare(var, CFStringRef(QAXFocusedAttribute), 0) == kCFCompareEqualTo) {
       
  2063         settable = true;
       
  2064     } else {
       
  2065         for (int r = 0; text_bindings[r][0].qt != -1; r++) {
       
  2066             if(interface.role() == (QAccessible::Role)text_bindings[r][0].qt) {
       
  2067                 for (int a = 1; text_bindings[r][a].qt != -1; a++) {
       
  2068                     if (CFStringCompare(var, CFStringRef(text_bindings[r][a].mac), 0) == kCFCompareEqualTo) {
       
  2069                         settable = text_bindings[r][a].settable;
       
  2070                         break;
       
  2071                     }
       
  2072                 }
       
  2073             }
       
  2074         }
       
  2075     }
       
  2076     SetEventParameter(event, kEventParamAccessibleAttributeSettable, typeBoolean,
       
  2077                       sizeof(settable), &settable);
       
  2078     return noErr;
       
  2079 }
       
  2080 
       
  2081 static OSStatus getChildAtPoint(EventHandlerCallRef next_ref, EventRef event, QAInterface &interface)
       
  2082 {
       
  2083     Q_UNUSED(next_ref);
       
  2084     if (interface.isValid() == false)
       
  2085         return eventNotHandledErr;
       
  2086 
       
  2087     // Add the children for this interface to the global QAccessibelHierachyManager.
       
  2088     accessibleHierarchyManager()->registerChildren(interface);
       
  2089 
       
  2090     Point where;
       
  2091     GetEventParameter(event, kEventParamMouseLocation, typeQDPoint, 0, sizeof(where), 0, &where);
       
  2092     const QAInterface childInterface = interface.childAt(where.h, where.v);
       
  2093 
       
  2094     if (childInterface.isValid() == false || childInterface == interface)
       
  2095         return eventNotHandledErr;
       
  2096 
       
  2097     const QAElement element = accessibleHierarchyManager()->lookup(childInterface);
       
  2098     if (element.isValid() == false)
       
  2099         return eventNotHandledErr;
       
  2100 
       
  2101     AXUIElementRef elementRef = element.element();
       
  2102     CFRetain(elementRef);
       
  2103     SetEventParameter(event, kEventParamAccessibleChild, typeCFTypeRef,
       
  2104                                   sizeof(elementRef), &elementRef);
       
  2105 
       
  2106     return noErr;
       
  2107 }
       
  2108 
       
  2109 /*
       
  2110     Returns a list of actions the given interface supports.
       
  2111     Currently implemented by getting the interface role and deciding based on that.
       
  2112 */
       
  2113 static QList<QAccessible::Action> supportedPredefinedActions(const QAInterface &interface)
       
  2114 {
       
  2115     QList<QAccessible::Action> actions;
       
  2116     switch (interface.role()) {
       
  2117         default:
       
  2118             // Most things can be pressed.
       
  2119             actions.append(QAccessible::Press);
       
  2120         break;
       
  2121     }
       
  2122 
       
  2123     return actions;
       
  2124 }
       
  2125 
       
  2126 /*
       
  2127     Translates a predefined QAccessible::Action to a Mac action constant.
       
  2128     Returns an empty string if the Qt Action has no mac equivalent.
       
  2129 */
       
  2130 static QCFString translateAction(const QAccessible::Action action)
       
  2131 {
       
  2132     switch (action) {
       
  2133         case QAccessible::Press:
       
  2134             return CFStringRef(QAXPressAction);
       
  2135         break;
       
  2136         case QAccessible::Increase:
       
  2137             return CFStringRef(QAXIncrementAction);
       
  2138         break;
       
  2139         case QAccessible::Decrease:
       
  2140             return CFStringRef(QAXDecrementAction);
       
  2141         break;
       
  2142         case QAccessible::Accept:
       
  2143             return CFStringRef(QAXConfirmAction);
       
  2144         break;
       
  2145         case QAccessible::Select:
       
  2146             return CFStringRef(QAXPickAction);
       
  2147         break;
       
  2148         case QAccessible::Cancel:
       
  2149             return CFStringRef(QAXCancelAction);
       
  2150         break;
       
  2151         default:
       
  2152             return QCFString();
       
  2153         break;
       
  2154     }
       
  2155 }
       
  2156 
       
  2157 /*
       
  2158     Translates between a Mac action constant and a QAccessible::Action.
       
  2159     Returns QAccessible::Default action if there is no Qt predefined equivalent.
       
  2160 */
       
  2161 static QAccessible::Action translateAction(const CFStringRef actionName)
       
  2162 {
       
  2163     if(CFStringCompare(actionName, CFStringRef(QAXPressAction), 0) == kCFCompareEqualTo) {
       
  2164         return QAccessible::Press;
       
  2165     } else if(CFStringCompare(actionName, CFStringRef(QAXIncrementAction), 0) == kCFCompareEqualTo) {
       
  2166         return QAccessible::Increase;
       
  2167     } else if(CFStringCompare(actionName, CFStringRef(QAXDecrementAction), 0) == kCFCompareEqualTo) {
       
  2168         return QAccessible::Decrease;
       
  2169     } else if(CFStringCompare(actionName, CFStringRef(QAXConfirmAction), 0) == kCFCompareEqualTo) {
       
  2170         return QAccessible::Accept;
       
  2171     } else if(CFStringCompare(actionName, CFStringRef(QAXPickAction), 0) == kCFCompareEqualTo) {
       
  2172         return QAccessible::Select;
       
  2173     } else if(CFStringCompare(actionName, CFStringRef(QAXCancelAction), 0) == kCFCompareEqualTo) {
       
  2174         return QAccessible::Cancel;
       
  2175     } else {
       
  2176         return QAccessible::DefaultAction;
       
  2177     }
       
  2178 }
       
  2179 #endif // QT_MAC_USE_COCOA
       
  2180 
       
  2181 /*
       
  2182     Copies the translated names all supported actions for an interface into the kEventParamAccessibleActionNames
       
  2183     event parameter.
       
  2184 */
       
  2185 #ifndef QT_MAC_USE_COCOA
       
  2186 static OSStatus getAllActionNames(EventHandlerCallRef next_ref, EventRef event, const QAInterface &interface)
       
  2187 {
       
  2188     Q_UNUSED(next_ref);
       
  2189 
       
  2190     CFMutableArrayRef actions = 0;
       
  2191     GetEventParameter(event, kEventParamAccessibleActionNames, typeCFMutableArrayRef, 0,
       
  2192                       sizeof(actions), 0, &actions);
       
  2193 
       
  2194     // Add supported predefined actions.
       
  2195     const QList<QAccessible::Action> predefinedActions = supportedPredefinedActions(interface);
       
  2196     for (int i = 0; i < predefinedActions.count(); ++i) {
       
  2197         const QCFString action = translateAction(predefinedActions.at(i));
       
  2198         if (action != QCFString())
       
  2199             qt_mac_append_cf_uniq(actions, action);
       
  2200     }
       
  2201 
       
  2202     // Add user actions
       
  2203     const int actionCount = interface.userActionCount();
       
  2204     for (int i = 0; i < actionCount; ++i) {
       
  2205         const QString actionName = interface.actionText(i, QAccessible::Name);
       
  2206         qt_mac_append_cf_uniq(actions, QCFString::toCFStringRef(actionName));
       
  2207     }
       
  2208 
       
  2209     return noErr;
       
  2210 }
       
  2211 #endif
       
  2212 
       
  2213 /*
       
  2214     Handles the perforNamedAction event.
       
  2215 */
       
  2216 #ifndef QT_MAC_USE_COCOA
       
  2217 static OSStatus performNamedAction(EventHandlerCallRef next_ref, EventRef event, const QAInterface& interface)
       
  2218 {
       
  2219     Q_UNUSED(next_ref);
       
  2220 
       
  2221     CFStringRef act;
       
  2222     GetEventParameter(event, kEventParamAccessibleActionName, typeCFStringRef, 0,
       
  2223                       sizeof(act), 0, &act);
       
  2224 
       
  2225     const QAccessible::Action action = translateAction(act);
       
  2226 
       
  2227     // Perform built-in action
       
  2228     if (action != QAccessible::DefaultAction) {
       
  2229         interface.doAction(action, QVariantList());
       
  2230         return noErr;
       
  2231     }
       
  2232 
       
  2233     // Search for user-defined actions and perform it if found.
       
  2234     const int actCount = interface.userActionCount();
       
  2235     const QString qAct = QCFString::toQString(act);
       
  2236     for(int i = 0; i < actCount; i++) {
       
  2237         if(interface.actionText(i, QAccessible::Name) == qAct) {
       
  2238             interface.doAction(i, QVariantList());
       
  2239             break;
       
  2240         }
       
  2241     }
       
  2242     return noErr;
       
  2243 }
       
  2244 
       
  2245 static OSStatus setNamedAttribute(EventHandlerCallRef next_ref, EventRef event, const QAInterface &interface)
       
  2246 {
       
  2247     Q_UNUSED(next_ref);
       
  2248     Q_UNUSED(event);
       
  2249 
       
  2250     CFStringRef var;
       
  2251     GetEventParameter(event, kEventParamAccessibleAttributeName, typeCFStringRef, 0,
       
  2252                       sizeof(var), 0, &var);
       
  2253     if(CFStringCompare(var, CFStringRef(QAXFocusedAttribute), 0) == kCFCompareEqualTo) {
       
  2254         CFTypeRef val;
       
  2255         if(GetEventParameter(event, kEventParamAccessibleAttributeValue, typeCFTypeRef, 0,
       
  2256                              sizeof(val), 0, &val) == noErr) {
       
  2257             if(CFGetTypeID(val) == CFBooleanGetTypeID() &&
       
  2258                CFEqual(static_cast<CFBooleanRef>(val), kCFBooleanTrue)) {
       
  2259                 interface.doAction(QAccessible::SetFocus);
       
  2260             }
       
  2261         }
       
  2262     } else {
       
  2263         bool found = false;
       
  2264         for(int r = 0; text_bindings[r][0].qt != -1; r++) {
       
  2265             if(interface.role() == (QAccessible::Role)text_bindings[r][0].qt) {
       
  2266                 for(int a = 1; text_bindings[r][a].qt != -1; a++) {
       
  2267                     if(CFStringCompare(var, CFStringRef(text_bindings[r][a].mac), 0) == kCFCompareEqualTo) {
       
  2268                         if(!text_bindings[r][a].settable) {
       
  2269                         } else {
       
  2270                             CFTypeRef val;
       
  2271                             if(GetEventParameter(event, kEventParamAccessibleAttributeValue, typeCFTypeRef, 0,
       
  2272                                                  sizeof(val), 0, &val) == noErr) {
       
  2273                                 if(CFGetTypeID(val) == CFStringGetTypeID())
       
  2274                                     interface.setText((QAccessible::Text)text_bindings[r][a].qt,
       
  2275                                                    QCFString::toQString(static_cast<CFStringRef>(val)));
       
  2276 
       
  2277                             }
       
  2278                         }
       
  2279                         found = true;
       
  2280                         break;
       
  2281                     }
       
  2282                 }
       
  2283                 break;
       
  2284             }
       
  2285         }
       
  2286     }
       
  2287     return noErr;
       
  2288 }
       
  2289 
       
  2290 /*
       
  2291     This is the main accessibility event handler.
       
  2292 */
       
  2293 static OSStatus accessibilityEventHandler(EventHandlerCallRef next_ref, EventRef event, void *data)
       
  2294 {
       
  2295     Q_UNUSED(data)
       
  2296 
       
  2297     // Return if this event is not a AccessibleGetNamedAttribute event.
       
  2298     const UInt32 eclass = GetEventClass(event);
       
  2299     if (eclass != kEventClassAccessibility)
       
  2300         return eventNotHandledErr;
       
  2301 
       
  2302     // Get the AXUIElementRef and QAInterface pointer
       
  2303     AXUIElementRef element = 0;
       
  2304     GetEventParameter(event, kEventParamAccessibleObject, typeCFTypeRef, 0, sizeof(element), 0, &element);
       
  2305     QAInterface interface = accessibleHierarchyManager()->lookup(element);
       
  2306     if (interface.isValid() == false)
       
  2307         return eventNotHandledErr;
       
  2308 
       
  2309     const UInt32 ekind = GetEventKind(event);
       
  2310     OSStatus status = noErr;
       
  2311     switch (ekind) {
       
  2312         case kEventAccessibleGetAllAttributeNames:
       
  2313              status = getAllAttributeNames(event, interface, next_ref);
       
  2314         break;
       
  2315         case kEventAccessibleGetNamedAttribute:
       
  2316              status = getNamedAttribute(next_ref, event, interface);
       
  2317         break;
       
  2318         case kEventAccessibleIsNamedAttributeSettable:
       
  2319              status = isNamedAttributeSettable(event, interface);
       
  2320         break;
       
  2321         case kEventAccessibleGetChildAtPoint:
       
  2322             status = getChildAtPoint(next_ref, event, interface);
       
  2323         break;
       
  2324         case kEventAccessibleGetAllActionNames:
       
  2325             status = getAllActionNames(next_ref, event, interface);
       
  2326         break;
       
  2327         case kEventAccessibleGetFocusedChild:
       
  2328             status = CallNextEventHandler(next_ref, event);
       
  2329         break;
       
  2330         case kEventAccessibleSetNamedAttribute:
       
  2331             status = setNamedAttribute(next_ref, event, interface);
       
  2332         break;
       
  2333         case kEventAccessiblePerformNamedAction:
       
  2334             status = performNamedAction(next_ref, event, interface);
       
  2335         break;
       
  2336         default:
       
  2337             status = CallNextEventHandler(next_ref, event);
       
  2338         break;
       
  2339     };
       
  2340     return status;
       
  2341 }
       
  2342 #endif
       
  2343 
       
  2344 void QAccessible::initialize()
       
  2345 {
       
  2346 #ifndef QT_MAC_USE_COCOA
       
  2347     registerQtAccessibilityHIObjectSubclass();
       
  2348     installApplicationEventhandler();
       
  2349 #endif
       
  2350 }
       
  2351 
       
  2352 // Sets thre root object for the application
       
  2353 void QAccessible::setRootObject(QObject *object)
       
  2354 {
       
  2355     // Call installed root object handler if we have one
       
  2356     if (rootObjectHandler) {
       
  2357         rootObjectHandler(object);
       
  2358         return;
       
  2359     }
       
  2360 
       
  2361     rootObject = object;
       
  2362 }
       
  2363 
       
  2364 void QAccessible::cleanup()
       
  2365 {
       
  2366     accessibleHierarchyManager()->reset();
       
  2367 #ifndef QT_MAC_USE_COCOA
       
  2368     removeEventhandler(applicationEventHandlerUPP);
       
  2369     removeEventhandler(objectCreateEventHandlerUPP);
       
  2370     removeEventhandler(accessibilityEventHandlerUPP);
       
  2371 #endif
       
  2372 }
       
  2373 
       
  2374 void QAccessible::updateAccessibility(QObject *object, int child, Event reason)
       
  2375 {
       
  2376     // Call installed update handler if we have one.
       
  2377     if (updateHandler) {
       
  2378         updateHandler(object, child, reason);
       
  2379         return;
       
  2380     }
       
  2381 
       
  2382 #ifndef QT_MAC_USE_COCOA
       
  2383     // Return if the mac accessibility is not enabled.
       
  2384     if(!AXAPIEnabled())
       
  2385         return;
       
  2386 
       
  2387      // Work around crash, disable accessiblity for focus frames.
       
  2388      if (qstrcmp(object->metaObject()->className(), "QFocusFrame") == 0)
       
  2389         return;
       
  2390 
       
  2391 //    qDebug() << "updateAccessibility" << object << child << hex << reason;
       
  2392 
       
  2393     if (reason == ObjectShow) {
       
  2394         QAInterface interface = QAInterface(QAccessible::queryAccessibleInterface(object), child);
       
  2395         accessibleHierarchyManager()->registerInterface(interface);
       
  2396     }
       
  2397 
       
  2398     const QAElement element = accessibleHierarchyManager()->lookup(object, child);
       
  2399     if (element.isValid() == false)
       
  2400         return;
       
  2401 
       
  2402 
       
  2403     CFStringRef notification = 0;
       
  2404     if(object && object->isWidgetType() && reason == ObjectCreated) {
       
  2405         notification = CFStringRef(QAXWindowCreatedNotification);
       
  2406     } else if(reason == ValueChanged) {
       
  2407         notification = CFStringRef(QAXValueChangedNotification);
       
  2408     } else if(reason == MenuStart) {
       
  2409         notification = CFStringRef(QAXMenuOpenedNotification);
       
  2410     } else if(reason == MenuEnd) {
       
  2411         notification = CFStringRef(QAXMenuClosedNotification);
       
  2412     } else if(reason == LocationChanged) {
       
  2413         notification = CFStringRef(QAXWindowMovedNotification);
       
  2414     } else if(reason == ObjectShow || reason == ObjectHide ) {
       
  2415         // When a widget is deleted we get a ObjectHide before the destroyed(QObject *)
       
  2416         // signal is emitted (which makes sense). However, at this point we are in the
       
  2417         // middle of the QWidget destructor which means that we have to be careful when
       
  2418         // using the widget pointer. Since we can't control what the accessibilty interfaces
       
  2419         // does when navigate() is called below we ignore the hide update in this case.
       
  2420         // (the widget will be deleted soon anyway.)
       
  2421         extern QWidgetPrivate * qt_widget_private(QWidget *);
       
  2422         if (QWidget *widget = qobject_cast<QWidget*>(object)) {
       
  2423             if (qt_widget_private(widget)->data.in_destructor)
       
  2424                 return;
       
  2425 
       
  2426             // Check widget parent as well, special case for preventing crash
       
  2427             // when the viewport() of an abstract scroll area is hidden when
       
  2428             // the QWidget destructor hides all its children.
       
  2429             QWidget *parentWidget = widget->parentWidget();
       
  2430             if (parentWidget && qt_widget_private(parentWidget)->data.in_destructor)
       
  2431                 return;
       
  2432         }
       
  2433 
       
  2434         // There is no equivalent Mac notification for ObjectShow/Hide, so we call HIObjectSetAccessibilityIgnored
       
  2435         // and isItIntersting which will mark the HIObject accociated with the element as ignored if the
       
  2436         // QAccessible::Invisible state bit is set.
       
  2437         QAInterface interface = accessibleHierarchyManager()->lookup(element);
       
  2438         if (interface.isValid()) {
       
  2439             HIObjectSetAccessibilityIgnored(element.object(), !isItInteresting(interface));
       
  2440         }
       
  2441 
       
  2442         // If the interface manages its own children, also check if we should ignore those.
       
  2443         if (isItemView(interface) == false && managesChildren(interface)) {
       
  2444             for (int i = 1; i <= interface.childCount(); ++i) {
       
  2445                 QAInterface childInterface = interface.navigate(QAccessible::Child, i);
       
  2446                 if (childInterface.isValid() && childInterface.isHIView() == false) {
       
  2447                     const QAElement element = accessibleHierarchyManager()->lookup(childInterface);
       
  2448                     if (element.isValid()) {
       
  2449                         HIObjectSetAccessibilityIgnored(element.object(), !isItInteresting(childInterface));
       
  2450                     }
       
  2451                 }
       
  2452             }
       
  2453         }
       
  2454 
       
  2455     } else if(reason == Focus) {
       
  2456         if(object && object->isWidgetType()) {
       
  2457             QWidget *w = static_cast<QWidget*>(object);
       
  2458             if(w->isWindow())
       
  2459                 notification = CFStringRef(QAXFocusedWindowChangedNotification);
       
  2460             else
       
  2461                 notification = CFStringRef(QAXFocusedUIElementChangedNotification);
       
  2462         }
       
  2463     }
       
  2464 
       
  2465     if (!notification)
       
  2466         return;
       
  2467 
       
  2468     AXNotificationHIObjectNotify(notification, element.object(), element.id());
       
  2469 #endif
       
  2470 }
       
  2471 
       
  2472 QT_END_NAMESPACE
       
  2473 
       
  2474 #endif // QT_NO_ACCESSIBILITY