src/gui/accessible/qaccessible_mac.mm
changeset 0 1918ee327afb
child 3 41300fa6a67c
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/gui/accessible/qaccessible_mac.mm	Mon Jan 11 14:00:40 2010 +0000
@@ -0,0 +1,2474 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file.  Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights.  These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qaccessible.h"
+
+#ifndef QT_NO_ACCESSIBILITY
+#include "qaccessible_mac_p.h"
+#include "qhash.h"
+#include "qset.h"
+#include "qpointer.h"
+#include "qapplication.h"
+#include "qmainwindow.h"
+#include "qtextdocument.h"
+#include "qdebug.h"
+#include "qabstractslider.h"
+#include "qsplitter.h"
+#include "qtabwidget.h"
+#include "qlistview.h"
+#include "qtableview.h"
+#include "qdockwidget.h"
+
+#include <private/qt_mac_p.h>
+#include <private/qwidget_p.h>
+#include <CoreFoundation/CoreFoundation.h>
+
+QT_BEGIN_NAMESPACE
+
+/*
+    Set up platform defines. There is a one-to-one correspondence between the
+    Carbon and Cocoa roles and attributes, but the prefix and type changes.
+*/
+#ifdef QT_MAC_USE_COCOA
+typedef NSString * const QAXRoleType;
+#define QAXApplicationRole NSAccessibilityApplicationRole
+#define QAXButtonRole NSAccessibilityButtonRole
+#define QAXCancelAction NSAccessibilityCancelAction
+#define QAXCheckBoxRole NSAccessibilityCheckBoxRole
+#define QAXChildrenAttribute NSAccessibilityChildrenAttribute
+#define QAXCloseButtonAttribute NSAccessibilityCloseButtonAttribute
+#define QAXCloseButtonAttribute NSAccessibilityCloseButtonAttribute
+#define QAXColumnRole NSAccessibilityColumnRole
+#define QAXConfirmAction NSAccessibilityConfirmAction
+#define QAXContentsAttribute NSAccessibilityContentsAttribute
+#define QAXDecrementAction NSAccessibilityDecrementAction
+#define QAXDecrementArrowSubrole NSAccessibilityDecrementArrowSubrole
+#define QAXDecrementPageSubrole NSAccessibilityDecrementPageSubrole
+#define QAXDescriptionAttribute NSAccessibilityDescriptionAttribute
+#define QAXEnabledAttribute NSAccessibilityEnabledAttribute
+#define QAXExpandedAttribute NSAccessibilityExpandedAttribute
+#define QAXFocusedAttribute NSAccessibilityFocusedAttribute
+#define QAXFocusedUIElementChangedNotification NSAccessibilityFocusedUIElementChangedNotification
+#define QAXFocusedWindowChangedNotification NSAccessibilityFocusedWindowChangedNotification
+#define QAXGroupRole NSAccessibilityGroupRole
+#define QAXGrowAreaAttribute NSAccessibilityGrowAreaAttribute
+#define QAXGrowAreaRole NSAccessibilityGrowAreaRole
+#define QAXHelpAttribute NSAccessibilityHelpAttribute
+#define QAXHorizontalOrientationValue NSAccessibilityHorizontalOrientationValue
+#define QAXHorizontalScrollBarAttribute NSAccessibilityHorizontalScrollBarAttribute
+#define QAXIncrementAction NSAccessibilityIncrementAction
+#define QAXIncrementArrowSubrole NSAccessibilityIncrementArrowSubrole
+#define QAXIncrementPageSubrole NSAccessibilityIncrementPageSubrole
+#define QAXIncrementorRole NSAccessibilityIncrementorRole
+#define QAXLinkedUIElementsAttribute NSAccessibilityLinkedUIElementsAttribute
+#define QAXListRole NSAccessibilityListRole
+#define QAXMainAttribute NSAccessibilityMainAttribute
+#define QAXMaxValueAttribute NSAccessibilityMaxValueAttribute
+#define QAXMenuBarRole NSAccessibilityMenuBarRole
+#define QAXMenuButtonRole NSAccessibilityMenuButtonRole
+#define QAXMenuClosedNotification NSAccessibilityMenuClosedNotification
+#define QAXMenuItemRole NSAccessibilityMenuItemRole
+#define QAXMenuOpenedNotification NSAccessibilityMenuOpenedNotification
+#define QAXMenuRole NSAccessibilityMenuRole
+#define QAXMinValueAttribute NSAccessibilityMinValueAttribute
+#define QAXMinimizeButtonAttribute NSAccessibilityMinimizeButtonAttribute
+#define QAXMinimizedAttribute NSAccessibilityMinimizedAttribute
+#define QAXNextContentsAttribute NSAccessibilityNextContentsAttribute
+#define QAXOrientationAttribute NSAccessibilityOrientationAttribute
+#define QAXParentAttribute NSAccessibilityParentAttribute
+#define QAXPickAction NSAccessibilityPickAction
+#define QAXPopUpButtonRole NSAccessibilityPopUpButtonRole
+#define QAXPositionAttribute NSAccessibilityPositionAttribute
+#define QAXPressAction NSAccessibilityPressAction
+#define QAXPreviousContentsAttribute NSAccessibilityPreviousContentsAttribute
+#define QAXProgressIndicatorRole NSAccessibilityProgressIndicatorRole
+#define QAXRadioButtonRole NSAccessibilityRadioButtonRole
+#define QAXRoleAttribute NSAccessibilityRoleAttribute
+#define QAXRoleDescriptionAttribute NSAccessibilityRoleDescriptionAttribute
+#define QAXRowRole NSAccessibilityRowRole
+#define QAXRowsAttribute NSAccessibilityRowsAttribute
+#define QAXScrollAreaRole NSAccessibilityScrollAreaRole
+#define QAXScrollBarRole NSAccessibilityScrollBarRole
+#define QAXSelectedAttribute NSAccessibilitySelectedAttribute
+#define QAXSelectedChildrenAttribute NSAccessibilitySelectedChildrenAttribute
+#define QAXSelectedRowsAttribute NSAccessibilitySelectedRowsAttribute
+#define QAXSizeAttribute NSAccessibilitySizeAttribute
+#define QAXSliderRole NSAccessibilitySliderRole
+#define QAXSplitGroupRole NSAccessibilitySplitGroupRole
+#define QAXSplitterRole NSAccessibilitySplitterRole
+#define QAXSplittersAttribute NSAccessibilitySplittersAttribute
+#define QAXStaticTextRole NSAccessibilityStaticTextRole
+#define QAXSubroleAttribute NSAccessibilitySubroleAttribute
+#define QAXSubroleAttribute NSAccessibilitySubroleAttribute
+#define QAXTabGroupRole NSAccessibilityTabGroupRole
+#define QAXTableRole NSAccessibilityTableRole
+#define QAXTabsAttribute NSAccessibilityTabsAttribute
+#define QAXTextFieldRole NSAccessibilityTextFieldRole
+#define QAXTitleAttribute NSAccessibilityTitleAttribute
+#define QAXTitleUIElementAttribute NSAccessibilityTitleUIElementAttribute
+#define QAXToolbarButtonAttribute NSAccessibilityToolbarButtonAttribute
+#define QAXToolbarRole NSAccessibilityToolbarRole
+#define QAXTopLevelUIElementAttribute NSAccessibilityTopLevelUIElementAttribute
+#define QAXUnknownRole NSAccessibilityUnknownRole
+#define QAXValueAttribute NSAccessibilityValueAttribute
+#define QAXValueChangedNotification NSAccessibilityValueChangedNotification
+#define QAXValueIndicatorRole NSAccessibilityValueIndicatorRole
+#define QAXVerticalOrientationValue NSAccessibilityVerticalOrientationValue
+#define QAXVerticalScrollBarAttribute NSAccessibilityVerticalScrollBarAttribute
+#define QAXVisibleRowsAttribute NSAccessibilityVisibleRowsAttribute
+#define QAXWindowAttribute NSAccessibilityWindowAttribute
+#define QAXWindowCreatedNotification NSAccessibilityWindowCreatedNotification
+#define QAXWindowMovedNotification NSAccessibilityWindowMovedNotification
+#define QAXWindowRole NSAccessibilityWindowRole
+#define QAXZoomButtonAttribute NSAccessibilityZoomButtonAttribute
+#else
+typedef CFStringRef const QAXRoleType;
+#define QAXApplicationRole kAXApplicationRole
+#define QAXButtonRole kAXButtonRole
+#define QAXCancelAction kAXCancelAction
+#define QAXCheckBoxRole kAXCheckBoxRole
+#define QAXChildrenAttribute kAXChildrenAttribute
+#define QAXCloseButtonAttribute kAXCloseButtonAttribute
+#define QAXColumnRole kAXColumnRole
+#define QAXConfirmAction kAXConfirmAction
+#define QAXContentsAttribute kAXContentsAttribute
+#define QAXDecrementAction kAXDecrementAction
+#define QAXDecrementArrowSubrole kAXDecrementArrowSubrole
+#define QAXDecrementPageSubrole kAXDecrementPageSubrole
+#define QAXDescriptionAttribute kAXDescriptionAttribute
+#define QAXEnabledAttribute kAXEnabledAttribute
+#define QAXExpandedAttribute kAXExpandedAttribute
+#define QAXFocusedAttribute kAXFocusedAttribute
+#define QAXFocusedUIElementChangedNotification kAXFocusedUIElementChangedNotification
+#define QAXFocusedWindowChangedNotification kAXFocusedWindowChangedNotification
+#define QAXGroupRole kAXGroupRole
+#define QAXGrowAreaAttribute kAXGrowAreaAttribute
+#define QAXGrowAreaRole kAXGrowAreaRole
+#define QAXHelpAttribute kAXHelpAttribute
+#define QAXHorizontalOrientationValue kAXHorizontalOrientationValue
+#define QAXHorizontalScrollBarAttribute kAXHorizontalScrollBarAttribute
+#define QAXIncrementAction kAXIncrementAction
+#define QAXIncrementArrowSubrole kAXIncrementArrowSubrole
+#define QAXIncrementPageSubrole kAXIncrementPageSubrole
+#define QAXIncrementorRole kAXIncrementorRole
+#define QAXLinkedUIElementsAttribute kAXLinkedUIElementsAttribute
+#define QAXListRole kAXListRole
+#define QAXMainAttribute kAXMainAttribute
+#define QAXMaxValueAttribute kAXMaxValueAttribute
+#define QAXMenuBarRole kAXMenuBarRole
+#define QAXMenuButtonRole kAXMenuButtonRole
+#define QAXMenuClosedNotification kAXMenuClosedNotification
+#define QAXMenuItemRole kAXMenuItemRole
+#define QAXMenuOpenedNotification kAXMenuOpenedNotification
+#define QAXMenuRole kAXMenuRole
+#define QAXMinValueAttribute kAXMinValueAttribute
+#define QAXMinimizeButtonAttribute kAXMinimizeButtonAttribute
+#define QAXMinimizedAttribute kAXMinimizedAttribute
+#define QAXNextContentsAttribute kAXNextContentsAttribute
+#define QAXOrientationAttribute kAXOrientationAttribute
+#define QAXParentAttribute kAXParentAttribute
+#define QAXPickAction kAXPickAction
+#define QAXPopUpButtonRole kAXPopUpButtonRole
+#define QAXPositionAttribute kAXPositionAttribute
+#define QAXPressAction kAXPressAction
+#define QAXPreviousContentsAttribute kAXPreviousContentsAttribute
+#define QAXProgressIndicatorRole kAXProgressIndicatorRole
+#define QAXRadioButtonRole kAXRadioButtonRole
+#define QAXRoleAttribute kAXRoleAttribute
+#define QAXRoleDescriptionAttribute kAXRoleDescriptionAttribute
+#define QAXRowRole kAXRowRole
+#define QAXRowsAttribute kAXRowsAttribute
+#define QAXScrollAreaRole kAXScrollAreaRole
+#define QAXScrollBarRole kAXScrollBarRole
+#define QAXSelectedAttribute kAXSelectedAttribute
+#define QAXSelectedChildrenAttribute kAXSelectedChildrenAttribute
+#define QAXSelectedRowsAttribute kAXSelectedRowsAttribute
+#define QAXSizeAttribute kAXSizeAttribute
+#define QAXSliderRole kAXSliderRole
+#define QAXSplitGroupRole kAXSplitGroupRole
+#define QAXSplitterRole kAXSplitterRole
+#define QAXSplittersAttribute kAXSplittersAttribute
+#define QAXStaticTextRole kAXStaticTextRole
+#define QAXSubroleAttribute kAXSubroleAttribute
+#define QAXTabGroupRole kAXTabGroupRole
+#define QAXTableRole kAXTableRole
+#define QAXTabsAttribute kAXTabsAttribute
+#define QAXTextFieldRole kAXTextFieldRole
+#define QAXTitleAttribute kAXTitleAttribute
+#define QAXTitleUIElementAttribute kAXTitleUIElementAttribute
+#define QAXToolbarButtonAttribute kAXToolbarButtonAttribute
+#define QAXToolbarRole kAXToolbarRole
+#define QAXTopLevelUIElementAttribute kAXTopLevelUIElementAttribute
+#define QAXUnknownRole kAXUnknownRole
+#define QAXValueAttribute kAXValueAttribute
+#define QAXValueChangedNotification kAXValueChangedNotification
+#define QAXValueIndicatorRole kAXValueIndicatorRole
+#define QAXVerticalOrientationValue kAXVerticalOrientationValue
+#define QAXVerticalScrollBarAttribute kAXVerticalScrollBarAttribute
+#define QAXVisibleRowsAttribute kAXVisibleRowsAttribute
+#define QAXWindowAttribute kAXWindowAttribute
+#define QAXWindowCreatedNotification kAXWindowCreatedNotification
+#define QAXWindowMovedNotification kAXWindowMovedNotification
+#define QAXWindowRole kAXWindowRole
+#define QAXZoomButtonAttribute kAXZoomButtonAttribute
+#endif
+
+
+/*****************************************************************************
+  Externals
+ *****************************************************************************/
+extern bool qt_mac_is_macsheet(const QWidget *w); //qwidget_mac.cpp
+extern bool qt_mac_is_macdrawer(const QWidget *w); //qwidget_mac.cpp
+
+/*****************************************************************************
+  QAccessible Bindings
+ *****************************************************************************/
+//hardcoded bindings between control info and (known) QWidgets
+struct QAccessibleTextBinding {
+    int qt;
+    QAXRoleType mac;
+    bool settable;
+} text_bindings[][10] = {
+    { { QAccessible::MenuItem, QAXMenuItemRole, false },
+      { -1, 0, false }
+    },
+    { { QAccessible::MenuBar, QAXMenuBarRole, false },
+      { -1, 0, false }
+    },
+    { { QAccessible::ScrollBar, QAXScrollBarRole, false },
+      { -1, 0, false }
+    },
+    { { QAccessible::Grip, QAXGrowAreaRole, false },
+      { -1, 0, false }
+    },
+    { { QAccessible::Window, QAXWindowRole, false },
+      { -1, 0, false }
+    },
+    { { QAccessible::Dialog, QAXWindowRole, false },
+      { -1, 0, false }
+    },
+    { { QAccessible::AlertMessage, QAXWindowRole, false },
+      { -1, 0, false }
+    },
+    { { QAccessible::ToolTip, QAXWindowRole, false },
+      { -1, 0, false }
+    },
+    { { QAccessible::HelpBalloon, QAXWindowRole, false },
+      { -1, 0, false }
+    },
+    { { QAccessible::PopupMenu, QAXMenuRole, false },
+      { -1, 0, false }
+    },
+    { { QAccessible::Application, QAXApplicationRole, false },
+      { -1, 0, false }
+    },
+    { { QAccessible::Pane, QAXGroupRole, false },
+      { -1, 0, false }
+    },
+    { { QAccessible::Grouping, QAXGroupRole, false },
+      { -1, 0, false }
+    },
+    { { QAccessible::Separator, QAXSplitterRole, false },
+      { -1, 0, false }
+    },
+    { { QAccessible::ToolBar, QAXToolbarRole, false },
+      { -1, 0, false }
+    },
+    { { QAccessible::PageTab, QAXRadioButtonRole, false },
+      { -1, 0, false }
+    },
+    { { QAccessible::ButtonMenu, QAXMenuButtonRole, false },
+      { -1, 0, false }
+    },
+    { { QAccessible::ButtonDropDown, QAXPopUpButtonRole, false },
+      { -1, 0, false }
+    },
+    { { QAccessible::SpinBox, QAXIncrementorRole, false },
+      { -1, 0, false }
+    },
+    { { QAccessible::Slider, QAXSliderRole, false },
+      { -1, 0, false }
+    },
+    { { QAccessible::ProgressBar, QAXProgressIndicatorRole, false },
+      { -1, 0, false }
+    },
+    { { QAccessible::ComboBox, QAXPopUpButtonRole, false },
+      { -1, 0, false }
+    },
+    { { QAccessible::RadioButton, QAXRadioButtonRole, false },
+      { -1, 0, false }
+    },
+    { { QAccessible::CheckBox, QAXCheckBoxRole, false },
+      { -1, 0, false }
+    },
+    { { QAccessible::StaticText, QAXStaticTextRole, false },
+      { QAccessible::Name, QAXValueAttribute, false },
+      { -1, 0, false }
+    },
+    { { QAccessible::Table, QAXTableRole, false },
+      { -1, 0, false }
+    },
+    { { QAccessible::StatusBar, QAXStaticTextRole, false },
+      { -1, 0, false }
+    },
+    { { QAccessible::Column, QAXColumnRole, false },
+      { -1, 0, false }
+    },
+    { { QAccessible::ColumnHeader, QAXColumnRole, false },
+      { -1, 0, false }
+    },
+    { { QAccessible::Row, QAXRowRole, false },
+      { -1, 0, false }
+    },
+    { { QAccessible::RowHeader, QAXRowRole, false },
+      { -1, 0, false }
+    },
+    { { QAccessible::Cell, QAXTextFieldRole, false },
+      { -1, 0, false }
+    },
+    { { QAccessible::PushButton, QAXButtonRole, false },
+      { -1, 0, false }
+    },
+    { { QAccessible::EditableText, QAXTextFieldRole, true },
+      { -1, 0, false }
+    },
+    { { QAccessible::Link, QAXTextFieldRole, false },
+      { -1, 0, false }
+    },
+    { { QAccessible::Indicator, QAXValueIndicatorRole, false },
+      { -1, 0, false }
+    },
+    { { QAccessible::Splitter, QAXSplitGroupRole, false },
+      { -1, 0, false }
+    },
+    { { QAccessible::List, QAXListRole, false },
+      { -1, 0, false }
+    },
+    { { QAccessible::ListItem, QAXStaticTextRole, false },
+      { -1, 0, false }
+    },
+    { { QAccessible::Cell, QAXStaticTextRole, false },
+      { -1, 0, false }
+    },
+    { { -1, 0, false } }
+};
+
+class QAInterface;
+static CFStringRef macRole(const QAInterface &interface);
+
+QDebug operator<<(QDebug debug, const QAInterface &interface)
+{
+    if (interface.isValid() == false)
+        debug << "invalid interface";
+    else 
+        debug << interface.object() << "id" << interface.id() << "role" << hex << interface.role();
+    return debug;
+}
+
+// The root of the Qt accessible hiearchy.
+static QObject *rootObject = 0;
+
+
+bool QAInterface::operator==(const QAInterface &other) const
+{
+    if (isValid() == false || other.isValid() == false)
+        return (isValid() && other.isValid());
+    
+    // walk up the parent chain, comparing child indexes, until we reach
+    // an interface that has a QObject.
+    QAInterface currentThis = *this;
+    QAInterface currentOther = other;
+    
+    while (currentThis.object() == 0) {
+        if (currentOther.object() != 0)
+            return false;
+
+        // fail if the child indexes in the two hirearchies don't match.
+        if (currentThis.parent().indexOfChild(currentThis) !=
+            currentOther.parent().indexOfChild(currentOther))
+            return false;
+
+        currentThis = currentThis.parent();
+        currentOther = currentOther.parent();
+    }
+    
+    return (currentThis.object() == currentOther.object() && currentThis.id() == currentOther.id());
+}
+
+bool QAInterface::operator!=(const QAInterface &other) const
+{
+    return !operator==(other);
+}
+
+uint qHash(const QAInterface &item)
+{
+    if (item.isValid())
+        return qHash(item.object()) + qHash(item.id());
+    else
+        return qHash(item.cachedObject()) + qHash(item.id());
+}
+
+QAInterface QAInterface::navigate(RelationFlag relation, int entry) const
+{
+        if (!checkValid())
+            return QAInterface();
+
+    // On a QAccessibleInterface that handles its own children we can short-circut
+    // the navigation if this QAInterface refers to one of the children:
+    if (child != 0) {
+        // The Ancestor interface will always be the same QAccessibleInterface with
+        // a child value of 0.
+        if (relation == QAccessible::Ancestor)
+            return QAInterface(*this, 0);
+
+        // The child hiearchy is only one level deep, so navigating to a child
+        // of a child is not possible.
+        if (relation == QAccessible::Child) {
+            return QAInterface();
+        }
+    }
+    QAccessibleInterface *child_iface = 0;
+
+    const int status = base.interface->navigate(relation, entry, &child_iface);
+
+    if (status == -1)
+        return QAInterface(); // not found;
+
+    // Check if target is a child of this interface.
+    if (!child_iface) {
+        return QAInterface(*this, status);
+    } else {
+        // Target is child_iface or a child of that (status decides).
+        return QAInterface(child_iface, status);
+    }
+}
+
+QAElement::QAElement()
+:elementRef(0)
+{}
+
+QAElement::QAElement(AXUIElementRef elementRef)
+:elementRef(elementRef)
+{
+    if (elementRef != 0) {
+        CFRetain(elementRef);
+        CFRetain(object());
+    }
+}
+
+QAElement::QAElement(const QAElement &element)
+:elementRef(element.elementRef)
+{
+    if (elementRef != 0) {
+        CFRetain(elementRef);
+        CFRetain(object());
+    }
+}
+
+QAElement::QAElement(HIObjectRef object, int child)
+    :elementRef(
+#ifndef QT_MAC_USE_COCOA
+                AXUIElementCreateWithHIObjectAndIdentifier(object, child)
+#endif
+)
+{
+#ifndef QT_MAC_USE_COCOA
+    if (object == 0) {
+        elementRef = 0; // Create invalid QAElement.
+    } else {
+        elementRef = AXUIElementCreateWithHIObjectAndIdentifier(object, child);
+        CFRetain(object);
+    }
+#else
+    Q_UNUSED(object);
+    Q_UNUSED(child);
+#endif
+}
+
+QAElement::~QAElement()
+{
+    if (elementRef != 0) {
+        CFRelease(object());
+        CFRelease(elementRef);
+    }
+}
+
+void QAElement::operator=(const QAElement &other)
+{
+    if (*this == other)
+        return;
+
+    if (elementRef != 0) {
+        CFRelease(object());
+        CFRelease(elementRef);
+    }
+
+    elementRef = other.elementRef;
+
+    if (elementRef != 0) {
+        CFRetain(elementRef);
+        CFRetain(object());
+    }
+}
+
+bool QAElement::operator==(const QAElement &other) const
+{
+    if (elementRef == 0 || other.elementRef == 0)
+        return (elementRef == other.elementRef);
+
+    return CFEqual(elementRef, other.elementRef);
+}
+
+uint qHash(QAElement element)
+{
+    return qHash(element.object()) + qHash(element.id());
+}
+
+#ifndef QT_MAC_USE_COCOA
+static QInterfaceFactory *createFactory(const QAInterface &interface);
+#endif
+Q_GLOBAL_STATIC(QAccessibleHierarchyManager, accessibleHierarchyManager);
+
+/*
+    Reomves all accessibility info accosiated with the sender object.
+*/
+void QAccessibleHierarchyManager::objectDestroyed(QObject *object)
+{
+    HIObjectRef hiObject = qobjectHiobjectHash.value(object);
+    delete qobjectElementHash.value(object);
+    qobjectElementHash.remove(object);
+    hiobjectInterfaceHash.remove(hiObject);
+}
+
+/*
+    Removes all stored items.
+*/
+void QAccessibleHierarchyManager::reset()
+{
+    qDeleteAll(qobjectElementHash);
+    qobjectElementHash.clear();
+    hiobjectInterfaceHash.clear();
+    qobjectHiobjectHash.clear();
+}
+
+QAccessibleHierarchyManager *QAccessibleHierarchyManager::instance()
+{
+    return accessibleHierarchyManager();
+}
+
+#ifndef QT_MAC_USE_COCOA
+static bool isItemView(const QAInterface &interface)
+{
+    QObject *object = interface.object();
+    return (interface.role() == QAccessible::List || interface.role() == QAccessible::Table
+            || (object && qobject_cast<QAbstractItemView *>(interface.object()))
+            || (object && object->objectName() == QLatin1String("qt_scrollarea_viewport")
+                && qobject_cast<QAbstractItemView *>(object->parent())));
+}
+#endif
+
+static bool isTabWidget(const QAInterface &interface)
+{
+    if (QObject *object = interface.object())
+        return (object->inherits("QTabWidget") && interface.id() == 0);
+    return false;
+}
+
+static bool isStandaloneTabBar(const QAInterface &interface)
+{
+    QObject *object = interface.object();
+    if (interface.role() == QAccessible::PageTabList && object)
+        return (qobject_cast<QTabWidget *>(object->parent()) == 0);
+
+    return false;
+}
+
+static bool isEmbeddedTabBar(const QAInterface &interface)
+{
+    QObject *object = interface.object();
+    if (interface.role() == QAccessible::PageTabList && object)
+        return (qobject_cast<QTabWidget *>(object->parent()));
+
+    return false;
+}
+
+/*
+    Decides if a QAInterface is interesting from an accessibility users point of view.
+*/
+bool isItInteresting(const QAInterface &interface)
+{
+    // Mac accessibility does not have an attribute that corresponds to the Invisible/Offscreen
+    // state, so we disable the interface here.
+    const QAccessible::State state = interface.state();
+    if (state & QAccessible::Invisible ||
+        state & QAccessible::Offscreen )
+        return false;
+
+    const QAccessible::Role role = interface.role();
+
+    if (QObject * const object = interface.object()) {
+        const QString className = QLatin1String(object->metaObject()->className());
+
+        // VoiceOver focusing on tool tips can be confusing. The contents of the
+        // tool tip is avalible through the description attribute anyway, so
+        // we disable accessibility for tool tips.
+        if (className == QLatin1String("QTipLabel"))
+            return false;
+
+        // Hide TabBars that has a QTabWidget parent (the tab widget handles the accessibility)
+        if (isEmbeddedTabBar(interface))
+            return false;
+
+         // Hide docked dockwidgets. ### causes infinitie loop in the apple accessibility code.
+     /*    if (QDockWidget *dockWidget = qobject_cast<QDockWidget *>(object)) {
+            if (dockWidget->isFloating() == false)
+                return false;        
+         }
+    */
+    }
+
+    // Client is a generic role returned by plain QWidgets or other
+    // widgets that does not have separate QAccessible interface, such
+    // as the TabWidget. Return false unless macRole gives the interface
+    // a special role.
+    if (role == QAccessible::Client && macRole(interface) == CFStringRef(QAXUnknownRole))
+        return false;
+
+    // Some roles are not interesting:
+    if (role == QAccessible::Border ||    // QFrame
+        role == QAccessible::Application || // We use the system-provided application element.
+        role == QAccessible::MenuItem)      // The system also provides the menu items.
+        return false;
+
+    // It is probably better to access the toolbar buttons directly than having
+    // to navigate through the toolbar.
+    if (role == QAccessible::ToolBar)
+        return false;
+
+    return true;
+}
+
+QAElement QAccessibleHierarchyManager::registerInterface(QObject *object, int child)
+{
+#ifndef QT_MAC_USE_COCOA
+    return registerInterface(QAInterface(QAccessible::queryAccessibleInterface(object), child));
+#else
+    Q_UNUSED(object);
+    Q_UNUSED(child);
+    return QAElement();
+#endif
+}
+
+/*
+    Creates a QAXUIelement that corresponds to the given QAInterface.
+*/
+QAElement QAccessibleHierarchyManager::registerInterface(const QAInterface &interface)
+{
+#ifndef QT_MAC_USE_COCOA
+    if (interface.isValid() == false)
+        return QAElement();
+    QAInterface objectInterface = interface.objectInterface();
+
+    QObject * qobject = objectInterface.object();
+    HIObjectRef hiobject = objectInterface.hiObject();
+    if (qobject == 0 || hiobject == 0)
+        return QAElement();
+
+    if (qobjectElementHash.contains(qobject) == false) {
+        registerInterface(qobject, hiobject, createFactory(interface));
+        HIObjectSetAccessibilityIgnored(hiobject, !isItInteresting(interface));
+    }
+
+    return QAElement(hiobject, interface.id());
+#else
+    Q_UNUSED(interface);
+    return QAElement();
+#endif
+}
+
+#ifndef QT_MAC_USE_COCOA
+#include "qaccessible_mac_carbon.cpp"
+#endif
+
+void QAccessibleHierarchyManager::registerInterface(QObject * qobject, HIObjectRef hiobject, QInterfaceFactory *interfaceFactory)
+{
+#ifndef QT_MAC_USE_COCOA
+    if (qobjectElementHash.contains(qobject) == false) {
+        qobjectElementHash.insert(qobject, interfaceFactory);
+        qobjectHiobjectHash.insert(qobject, hiobject);
+        connect(qobject, SIGNAL(destroyed(QObject *)), SLOT(objectDestroyed(QObject *)));
+    }
+
+    if (hiobjectInterfaceHash.contains(hiobject) == false) {
+        hiobjectInterfaceHash.insert(hiobject, interfaceFactory);
+        installAcessibilityEventHandler(hiobject);
+    }
+#else
+    Q_UNUSED(qobject);
+    Q_UNUSED(hiobject);
+    Q_UNUSED(interfaceFactory);
+#endif
+}
+
+void QAccessibleHierarchyManager::registerChildren(const QAInterface &interface)
+{
+    QObject * const object = interface.object();
+    if (object == 0)
+        return;
+
+    QInterfaceFactory *interfaceFactory = qobjectElementHash.value(object);
+    
+    if (interfaceFactory == 0)
+        return;
+
+    interfaceFactory->registerChildren();
+}
+
+QAInterface QAccessibleHierarchyManager::lookup(const AXUIElementRef &element)
+{
+     if (element == 0)
+        return QAInterface();
+#ifndef QT_MAC_USE_COCOA
+    HIObjectRef hiObject = AXUIElementGetHIObject(element);
+
+    QInterfaceFactory *factory = hiobjectInterfaceHash.value(hiObject);
+    if (factory == 0) {
+        return QAInterface();
+    }
+
+    UInt64 id;
+    AXUIElementGetIdentifier(element, &id);
+    return factory->interface(id);
+#else
+    return QAInterface();
+#endif;
+}
+
+QAInterface QAccessibleHierarchyManager::lookup(const QAElement &element)
+{
+    return lookup(element.element());
+}
+
+QAElement QAccessibleHierarchyManager::lookup(const QAInterface &interface)
+{
+    if (interface.isValid() == false)
+        return QAElement();
+
+    QInterfaceFactory *factory = qobjectElementHash.value(interface.objectInterface().object());
+    if (factory == 0)
+        return QAElement();
+
+    return factory->element(interface);
+}
+
+QAElement QAccessibleHierarchyManager::lookup(QObject * const object, int id)
+{
+    QInterfaceFactory *factory = qobjectElementHash.value(object);
+    if (factory == 0)
+        return QAElement();
+
+    return factory->element(id);
+}
+
+/*
+    Standard interface mapping, return the stored interface
+    or HIObjectRef, and there is an one-to-one mapping between
+    the identifier and child.
+*/
+class QStandardInterfaceFactory : public QInterfaceFactory
+{
+public:
+    QStandardInterfaceFactory(const QAInterface &interface)
+    : m_interface(interface), object(interface.hiObject())
+    {
+        CFRetain(object);
+    }
+    
+    ~QStandardInterfaceFactory()
+    {
+         CFRelease(object);
+    }
+
+    
+    QAInterface interface(UInt64 identifier)
+    {
+        const int child = identifier;
+        return QAInterface(m_interface, child);
+    }
+
+    QAElement element(int id)
+    {
+        return QAElement(object, id);
+    }
+
+    QAElement element(const QAInterface &interface)
+    {
+        if (interface.object() == 0)
+            return QAElement();
+        return QAElement(object, interface.id());
+    }
+
+    void registerChildren()
+    {
+        const int childCount = m_interface.childCount();
+        for (int i = 1; i <= childCount; ++i) {
+            accessibleHierarchyManager()->registerInterface(m_interface.navigate(QAccessible::Child, i));
+        }
+    }
+
+private:
+    QAInterface m_interface;
+    HIObjectRef object;
+};
+
+/*
+    Interface mapping where that creates one HIObject for each interface child.
+*/
+class QMultipleHIObjectFactory : public QInterfaceFactory
+{
+public:
+    QMultipleHIObjectFactory(const QAInterface &interface)
+    : m_interface(interface)
+    {  }
+    
+    ~QMultipleHIObjectFactory()
+    {
+        foreach (HIObjectRef object, objects) {
+            CFRelease(object);
+        }
+    }
+
+    QAInterface interface(UInt64 identifier)
+    {
+        const int child = identifier;
+        return QAInterface(m_interface, child);
+    }
+
+    QAElement element(int child)
+    {
+        if (child == 0)
+            return QAElement(m_interface.hiObject(), 0);
+        
+        if (child > objects.count())
+            return QAElement();
+
+        return QAElement(objects.at(child - 1), child);
+    }
+
+    void registerChildren()
+    {
+#ifndef QT_MAC_USE_COCOA
+        const int childCount = m_interface.childCount();
+        for (int i = 1; i <= childCount; ++i) {
+            HIObjectRef hiobject;
+            HIObjectCreate(kObjectQtAccessibility, 0, &hiobject);
+            objects.append(hiobject);
+              accessibleHierarchyManager()->registerInterface(m_interface.object(), hiobject, this);
+            HIObjectSetAccessibilityIgnored(hiobject, !isItInteresting(m_interface.navigate(QAccessible::Child, i)));
+        }
+#endif
+    }
+
+private:
+    QAInterface m_interface;
+    QList<HIObjectRef> objects;
+};
+
+class QItemViewInterfaceFactory : public QInterfaceFactory
+{
+public:
+    QItemViewInterfaceFactory(const QAInterface &interface)
+    : m_interface(interface), object(interface.hiObject())
+    {
+        CFRetain(object);
+        columnCount = 0;
+        if (QTableView * tableView = qobject_cast<QTableView *>(interface.parent().object())) {
+            if (tableView->model())
+                columnCount = tableView->model()->columnCount();
+            if (tableView->verticalHeader())
+                ++columnCount;
+        }
+    }
+    
+    ~QItemViewInterfaceFactory()
+    {
+        CFRelease(object);
+    }
+
+    QAInterface interface(UInt64 identifier)
+    {
+        if (identifier == 0)
+            return m_interface;
+
+        if (m_interface.role() == QAccessible::List)
+            return m_interface.childAt(identifier);
+        
+        if (m_interface.role() == QAccessible::Table) {
+            const int index = identifier;
+            if (index == 0)
+                return m_interface; // return the item view interface.
+           
+            const int rowIndex = (index - 1) / (columnCount + 1);
+            const int cellIndex = (index - 1)  % (columnCount + 1);
+/*
+            qDebug() << "index" << index;
+            qDebug() << "rowIndex" << rowIndex;
+            qDebug() << "cellIndex" << cellIndex;
+*/
+            const QAInterface rowInterface = m_interface.childAt(rowIndex + 1);
+
+            if ((cellIndex) == 0) // Is it a row?
+                return rowInterface;
+            else {
+                return rowInterface.childAt(cellIndex);
+            }
+        }
+
+        return QAInterface();
+    }
+
+    QAElement element(int id)
+    {
+        if (id != 0) {
+            return QAElement();
+        }
+        return QAElement(object, 0);
+    }
+
+    QAElement element(const QAInterface &interface)
+    {
+        if (interface.object() && interface.object() == m_interface.object()) {
+            return QAElement(object, 0);
+        } else if (m_interface.role() == QAccessible::List) {
+            if (interface.parent().object() && interface.parent().object() == m_interface.object())
+                return QAElement(object, m_interface.indexOfChild(interface));
+        } else if (m_interface.role() == QAccessible::Table) {
+            QAInterface currentInterface = interface;
+            int index = 0;
+
+            while (currentInterface.isValid() && currentInterface.object() == 0) {
+                const QAInterface parentInterface = currentInterface.parent();
+/*
+                qDebug() << "current index" << index;
+                qDebug() << "current interface" << interface;
+
+                qDebug() << "parent interface" << parentInterface;
+                qDebug() << "grandparent interface" << parentInterface.parent();
+                qDebug() << "childCount" << interface.childCount();
+                qDebug() << "index of child" << parentInterface.indexOfChild(currentInterface);
+*/
+                index += ((parentInterface.indexOfChild(currentInterface) - 1) * (currentInterface.childCount() + 1)) + 1;
+                currentInterface = parentInterface;
+//                qDebug() << "new current interface" << currentInterface;
+            }
+            if (currentInterface.object() == m_interface.object())
+                return QAElement(object, index);
+
+
+        }
+        return QAElement();
+    }
+
+    void registerChildren()
+    {
+        // Item view child interfraces don't have their own qobjects, so there is nothing to register here.
+    }
+
+private:
+    QAInterface m_interface;
+    HIObjectRef object;
+    int columnCount; // for table views;
+};
+
+#ifndef QT_MAC_USE_COCOA
+static bool managesChildren(const QAInterface &interface)
+{
+    return (interface.childCount() > 0 && interface.childAt(1).id() > 0);
+}
+
+static QInterfaceFactory *createFactory(const QAInterface &interface)
+{
+    if (isItemView(interface)) {
+        return new QItemViewInterfaceFactory(interface);
+    }  if (managesChildren(interface)) {
+        return new QMultipleHIObjectFactory(interface);
+    }
+
+    return new QStandardInterfaceFactory(interface);
+}
+#endif
+
+QList<QAElement> lookup(const QList<QAInterface> &interfaces)
+{
+    QList<QAElement> elements;
+    foreach (const QAInterface &interface, interfaces)
+        if (interface.isValid()) {
+            const QAElement element = accessibleHierarchyManager()->lookup(interface);
+            if (element.isValid())
+                elements.append(element);
+        }
+    return elements;
+}
+
+// Debug output helpers:
+/*
+static QString nameForEventKind(UInt32 kind)
+{
+    switch(kind) {
+        case kEventAccessibleGetChildAtPoint:       return QString("GetChildAtPoint");      break;
+        case kEventAccessibleGetAllAttributeNames:  return QString("GetAllAttributeNames"); break;
+        case kEventAccessibleGetNamedAttribute:     return QString("GetNamedAttribute");    break;
+        case kEventAccessibleSetNamedAttribute:     return QString("SetNamedAttribute");    break;
+        case kEventAccessibleGetAllActionNames:     return QString("GetAllActionNames");    break;
+        case kEventAccessibleGetFocusedChild:       return QString("GetFocusedChild");      break;
+        default:
+            return QString("Unknown accessibility event type: %1").arg(kind);
+        break;
+    };
+}
+*/
+#ifndef QT_MAC_USE_COCOA
+static bool qt_mac_append_cf_uniq(CFMutableArrayRef array, CFTypeRef value)
+{
+    if (value == 0)
+        return false; 
+
+    CFRange range;
+    range.location = 0;
+    range.length = CFArrayGetCount(array);
+    if(!CFArrayContainsValue(array, range, value)) {
+        CFArrayAppendValue(array, value);
+        return true;
+    }
+    return false;
+}
+
+static OSStatus setAttributeValue(EventRef event, const QList<QAElement> &elements)
+{
+    CFMutableArrayRef array = CFArrayCreateMutable(0, 0, &kCFTypeArrayCallBacks);
+    foreach (const QAElement &element, elements) {
+        if (element.isValid())
+            CFArrayAppendValue(array, element.element());
+    }
+
+    const OSStatus err = SetEventParameter(event, kEventParamAccessibleAttributeValue, 
+                                           typeCFTypeRef, sizeof(array), &array);
+    CFRelease(array);
+    return err;
+}
+#endif //QT_MAC_USE_COCOA
+
+/*
+    Gets the AccessibleObject parameter from an event.
+*/
+static inline AXUIElementRef getAccessibleObjectParameter(EventRef event)
+{
+    AXUIElementRef element;
+    GetEventParameter(event, kEventParamAccessibleObject, typeCFTypeRef, 0,
+                        sizeof(element), 0, &element);
+    return element;
+}
+
+/*
+    The application event handler makes sure that all top-level qt windows are registered
+    before any accessibility events are handeled.
+*/
+#ifndef QT_MAC_USE_COCOA
+static OSStatus applicationEventHandler(EventHandlerCallRef next_ref, EventRef event, void *)
+{
+    QAInterface rootInterface(QAccessible::queryAccessibleInterface(rootObject ? rootObject : qApp), 0);
+    accessibleHierarchyManager()->registerChildren(rootInterface);
+
+    return CallNextEventHandler(next_ref, event);
+}
+
+/*
+    Returns the value for element by combining the QAccessibility::Checked and
+    QAccessibility::Mixed flags into an int value that the Mac accessibilty
+    system understands. This works for check boxes, radio buttons, and the like.
+    The return values are:
+    0: unchecked
+    1: checked
+    2: undecided
+*/
+static int buttonValue(QAInterface element)
+{
+    const QAccessible::State state = element.state();
+    if (state & QAccessible::Mixed)
+        return 2;
+    else if(state & QAccessible::Checked)
+        return 1;
+    else
+        return 0;
+}
+
+static QString getValue(const QAInterface &interface)
+{
+    const QAccessible::Role role = interface.role();
+    if (role == QAccessible::RadioButton || role == QAccessible::CheckBox)
+        return QString::number(buttonValue(interface));
+    else
+        return interface.text(QAccessible::Value);
+}
+#endif //QT_MAC_USE_COCOA
+
+/*
+    Translates a QAccessible::Role into a mac accessibility role.
+*/
+static CFStringRef macRole(const QAInterface &interface)
+{
+    const QAccessible::Role qtRole = interface.role();
+
+//    qDebug() << "role for" << interface.object() << "interface role" << hex << qtRole;
+
+    // Qt accessibility:  QAccessible::Splitter contains QAccessible::Grip.
+    // Mac accessibility: AXSplitGroup contains AXSplitter.
+    if (qtRole == QAccessible::Grip) {
+        const QAInterface parent = interface.parent();
+        if (parent.isValid() && parent.role() == QAccessible::Splitter)
+            return CFStringRef(QAXSplitterRole);
+    }
+
+    // Tab widgets and standalone tab bars get the kAXTabGroupRole. Accessibility
+    // for tab bars emebedded in a tab widget is handled by the tab widget.
+    if (isTabWidget(interface) || isStandaloneTabBar(interface))
+        return kAXTabGroupRole;
+
+    if (QObject *object = interface.object()) {
+        // ### The interface for an abstract scroll area returns the generic "Client"
+        // role, so we have to to an extra detect on the QObject here.
+        if (object->inherits("QAbstractScrollArea") && interface.id() == 0)
+            return CFStringRef(QAXScrollAreaRole);
+
+        if (object->inherits("QDockWidget"))
+            return CFStringRef(QAXUnknownRole);
+    }
+
+    int i = 0;
+    int testRole = text_bindings[i][0].qt;
+    while (testRole != -1) {
+        if (testRole == qtRole)
+            return CFStringRef(text_bindings[i][0].mac);
+        ++i;
+        testRole = text_bindings[i][0].qt;
+    }
+
+//    qDebug() << "got unknown role!" << interface << interface.parent();
+
+    return CFStringRef(QAXUnknownRole);
+}
+
+/*
+    Translates a QAccessible::Role and an attribute name into a QAccessible::Text, taking into
+    account execptions listed in text_bindings.
+*/
+#ifndef QT_MAC_USE_COCOA
+static int textForRoleAndAttribute(QAccessible::Role role, CFStringRef attribute)
+{
+     // Search for exception, return it if found.
+    int testRole = text_bindings[0][0].qt;
+    int i = 0;
+    while (testRole != -1) {
+        if (testRole == role) {
+            int j = 1;
+            int qtRole = text_bindings[i][j].qt;
+            CFStringRef testAttribute = CFStringRef(text_bindings[i][j].mac);
+            while (qtRole != -1) {
+                if (CFStringCompare(attribute, testAttribute, 0) == kCFCompareEqualTo) {
+                    return (QAccessible::Text)qtRole;
+                }
+                ++j;
+                testAttribute = CFStringRef(text_bindings[i][j].mac); /// ### custom compare
+                qtRole = text_bindings[i][j].qt; /// ### custom compare
+            }
+            break;
+        }
+        ++i;
+        testRole = text_bindings[i][0].qt;
+    }
+
+    // Return default mappping
+    if (CFStringCompare(attribute, CFStringRef(QAXTitleAttribute), 0) == kCFCompareEqualTo)
+        return QAccessible::Name;
+    else if (CFStringCompare(attribute, CFStringRef(QAXValueAttribute), 0) == kCFCompareEqualTo)
+        return QAccessible::Value;
+    else if (CFStringCompare(attribute, CFStringRef(QAXHelpAttribute), 0) == kCFCompareEqualTo)
+        return QAccessible::Help;
+    else if (CFStringCompare(attribute, CFStringRef(QAXDescriptionAttribute), 0) == kCFCompareEqualTo)
+        return QAccessible::Description;
+    else
+        return -1;
+}
+
+/*
+    Returns the subrole string constant for the interface if it has one,
+    else returns an empty string.
+*/
+static QCFString subrole(const QAInterface &interface)
+{
+    const QAInterface parent = interface.parent();
+    if (parent.isValid() == false)
+        return QCFString();
+
+    if (parent.role() == QAccessible::ScrollBar) {
+        QCFString subrole;
+        switch(interface.id()) {
+            case 1: subrole = CFStringRef(QAXDecrementArrowSubrole); break;
+            case 2: subrole = CFStringRef(QAXDecrementPageSubrole); break;
+            case 4: subrole = CFStringRef(QAXIncrementPageSubrole); break;
+            case 5: subrole = CFStringRef(QAXIncrementArrowSubrole); break;
+            default:
+            break;
+        }
+        return subrole;
+    }
+    return QCFString();
+}
+
+// Gets the scroll bar orientation by asking the QAbstractSlider object directly.
+static Qt::Orientation scrollBarOrientation(const QAInterface &scrollBar)
+{
+    QObject *const object = scrollBar.object();
+    if (QAbstractSlider * const sliderObject = qobject_cast<QAbstractSlider * const>(object))
+        return sliderObject->orientation();
+
+    return Qt::Vertical; // D'oh! The interface wasn't a scroll bar.
+}
+
+static QAInterface scrollAreaGetScrollBarInterface(const QAInterface &scrollArea, Qt::Orientation orientation)
+{
+    if (macRole(scrollArea) != CFStringRef(CFStringRef(QAXScrollAreaRole)))
+        return QAInterface();
+
+    // Child 1 is the contents widget, 2 and 3 are the scroll bar containers wich contains possible scroll bars.
+    for (int i = 2; i <= 3; ++i) {
+        QAInterface scrollBarContainer = scrollArea.childAt(i);
+        for (int i = 1; i <= scrollBarContainer.childCount(); ++i) {
+            QAInterface scrollBar = scrollBarContainer.childAt(i);
+            if (scrollBar.isValid() &&
+                scrollBar.role() == QAccessible::ScrollBar &&
+                scrollBarOrientation(scrollBar) == orientation)
+                return scrollBar;
+        }
+    }
+
+    return QAInterface();
+}
+
+static bool scrollAreaHasScrollBar(const QAInterface &scrollArea, Qt::Orientation orientation)
+{
+    return scrollAreaGetScrollBarInterface(scrollArea, orientation).isValid();
+}
+
+static QAElement scrollAreaGetScrollBar(const QAInterface &scrollArea, Qt::Orientation orientation)
+{
+    return accessibleHierarchyManager()->lookup(scrollAreaGetScrollBarInterface(scrollArea, orientation));
+}
+
+static QAElement scrollAreaGetContents(const QAInterface &scrollArea)
+{
+    // Child 1 is the contents widget,
+    return accessibleHierarchyManager()->lookup(scrollArea.navigate(QAccessible::Child, 1));
+}
+
+static QAElement tabWidgetGetContents(const QAInterface &interface)
+{
+    // A kAXTabGroup has a kAXContents attribute, which consists of the
+    // ui elements for the current tab page. Get the current tab page
+    // from the QStackedWidget, where the current visible page can
+    // be found at index 1.
+    QAInterface stackedWidget = interface.childAt(1);
+    accessibleHierarchyManager()->registerChildren(stackedWidget);
+    QAInterface tabPageInterface = stackedWidget.childAt(1);
+    return accessibleHierarchyManager()->lookup(tabPageInterface);
+}
+
+static QList<QAElement> tabBarGetTabs(const QAInterface &interface)
+{
+    // Get the tabs by searching for children with the "PageTab" role.
+    // This filters out the left/right navigation buttons.
+    accessibleHierarchyManager()->registerChildren(interface);
+    QList<QAElement> tabs;
+    const int numChildren = interface.childCount();
+    for (int i = 1; i < numChildren + 1; ++i) {
+        QAInterface child = interface.navigate(QAccessible::Child, i);
+        if (child.isValid() && child.role() == QAccessible::PageTab) {
+            tabs.append(accessibleHierarchyManager()->lookup(child));
+        }
+    }
+    return tabs;
+}
+
+static QList<QAElement> tabWidgetGetTabs(const QAInterface &interface)
+{
+    // Each QTabWidget has two children, a QStackedWidget and a QTabBar.
+    // Get the tabs from the QTabBar.
+    return tabBarGetTabs(interface.childAt(2));
+}
+
+static QList<QAElement> tabWidgetGetChildren(const QAInterface &interface)
+{
+    // The children for a kAXTabGroup should consist of the tabs and the
+    // contents of the current open tab page.
+    QList<QAElement> children = tabWidgetGetTabs(interface);
+    children += tabWidgetGetContents(interface);
+    return children;
+}
+#endif //QT_MAC_USE_COCOA
+
+/*
+    Returns the label (buddy) interface for interface, or 0 if it has none.
+*/
+/*
+static QAInterface findLabel(const QAInterface &interface)
+{
+    return interface.navigate(QAccessible::Label, 1);
+}
+*/
+/*
+    Returns a list of interfaces this interface labels, or an empty list if it doesn't label any.
+*/
+/*
+static QList<QAInterface> findLabelled(const QAInterface &interface)
+{
+    QList<QAInterface> interfaceList;
+
+    int count = 1;
+    const QAInterface labelled = interface.navigate(QAccessible::Labelled, count);
+    while (labelled.isValid()) {
+        interfaceList.append(labelled);
+        ++count;
+    }
+    return interfaceList;
+}
+*/
+/*
+    Tests if the given QAInterface has data for a mac attribute.
+*/
+#ifndef QT_MAC_USE_COCOA
+static bool supportsAttribute(CFStringRef attribute, const QAInterface &interface)
+{
+    const int text = textForRoleAndAttribute(interface.role(), attribute);
+
+    // Special case: Static texts don't have a title.
+    if (interface.role() == QAccessible::StaticText && attribute == CFStringRef(QAXTitleAttribute))
+        return false;
+
+    // Return true if we the attribute matched a QAccessible::Role and we get text for that role from the interface.
+    if (text != -1) {
+        if (text == QAccessible::Value) // Special case for Value, see getValue()
+            return !getValue(interface).isEmpty();
+        else
+            return !interface.text((QAccessible::Text)text).isEmpty();
+    }
+
+    if (CFStringCompare(attribute, CFStringRef(QAXChildrenAttribute),  0) == kCFCompareEqualTo) {
+        if (interface.childCount() > 0)
+            return true;
+    }
+
+    if (CFStringCompare(attribute, CFStringRef(QAXSubroleAttribute),  0) == kCFCompareEqualTo) {
+        return (subrole(interface) != QCFString());
+    }
+
+    return false;
+}
+
+static void appendIfSupported(CFMutableArrayRef array, CFStringRef attribute, const QAInterface &interface)
+{
+    if (supportsAttribute(attribute, interface))
+        qt_mac_append_cf_uniq(array, attribute);
+}
+
+/*
+    Returns the names of the attributes the give QAInterface supports.
+*/
+static OSStatus getAllAttributeNames(EventRef event, const QAInterface &interface, EventHandlerCallRef next_ref)
+{
+    // Call system event handler.
+    OSStatus err = CallNextEventHandler(next_ref, event);
+    if(err != noErr && err != eventNotHandledErr)
+        return err;
+    CFMutableArrayRef attrs = 0;
+    GetEventParameter(event, kEventParamAccessibleAttributeNames, typeCFMutableArrayRef, 0,
+                      sizeof(attrs), 0, &attrs);
+
+    if (!attrs)
+        return eventNotHandledErr;
+
+    // Append attribute names that are always supported.
+    qt_mac_append_cf_uniq(attrs, CFStringRef(QAXPositionAttribute));
+    qt_mac_append_cf_uniq(attrs, CFStringRef(QAXSizeAttribute));
+    qt_mac_append_cf_uniq(attrs, CFStringRef(QAXRoleAttribute));
+    qt_mac_append_cf_uniq(attrs, CFStringRef(QAXEnabledAttribute));
+    qt_mac_append_cf_uniq(attrs, CFStringRef(QAXWindowAttribute));
+    qt_mac_append_cf_uniq(attrs, CFStringRef(QAXTopLevelUIElementAttribute));
+
+    // Append these names if the QInterafceItem returns any data for them.
+    appendIfSupported(attrs, CFStringRef(QAXTitleAttribute), interface);
+    appendIfSupported(attrs, CFStringRef(QAXValueAttribute), interface);
+    appendIfSupported(attrs, CFStringRef(QAXDescriptionAttribute), interface);
+    appendIfSupported(attrs, CFStringRef(QAXLinkedUIElementsAttribute), interface);
+    appendIfSupported(attrs, CFStringRef(QAXHelpAttribute), interface);
+    appendIfSupported(attrs, CFStringRef(QAXTitleUIElementAttribute), interface);
+    appendIfSupported(attrs, CFStringRef(QAXChildrenAttribute), interface);
+    appendIfSupported(attrs, CFStringRef(QAXSubroleAttribute), interface);
+
+    // Append attribute names based on the interaface role.
+    switch (interface.role())  {
+        case QAccessible::Window:
+            qt_mac_append_cf_uniq(attrs, CFStringRef(QAXMainAttribute));
+            qt_mac_append_cf_uniq(attrs, CFStringRef(QAXMinimizedAttribute));
+            qt_mac_append_cf_uniq(attrs, CFStringRef(QAXCloseButtonAttribute));
+            qt_mac_append_cf_uniq(attrs, CFStringRef(QAXZoomButtonAttribute));
+            qt_mac_append_cf_uniq(attrs, CFStringRef(QAXMinimizeButtonAttribute));
+            qt_mac_append_cf_uniq(attrs, CFStringRef(QAXToolbarButtonAttribute));
+            qt_mac_append_cf_uniq(attrs, CFStringRef(QAXGrowAreaAttribute));
+        break;
+        case QAccessible::RadioButton:
+        case QAccessible::CheckBox:
+            qt_mac_append_cf_uniq(attrs, CFStringRef(QAXMinValueAttribute));
+            qt_mac_append_cf_uniq(attrs, CFStringRef(QAXMaxValueAttribute));
+        break;
+        case QAccessible::ScrollBar:
+            qt_mac_append_cf_uniq(attrs, CFStringRef(QAXOrientationAttribute));
+        break;
+        case QAccessible::Splitter:
+            qt_mac_append_cf_uniq(attrs, CFStringRef(QAXSplittersAttribute));
+        break;
+        case QAccessible::Table:
+            qt_mac_append_cf_uniq(attrs, CFStringRef(QAXRowsAttribute));
+            qt_mac_append_cf_uniq(attrs, CFStringRef(QAXVisibleRowsAttribute));
+            qt_mac_append_cf_uniq(attrs, CFStringRef(QAXSelectedRowsAttribute));
+        break;
+        default:
+        break;
+    }
+
+    // Append attribute names based on the mac accessibility role.
+    const QCFString mac_role = macRole(interface);
+    if (mac_role == CFStringRef(QAXSplitterRole)) {
+        qt_mac_append_cf_uniq(attrs, CFStringRef(QAXPreviousContentsAttribute));
+        qt_mac_append_cf_uniq(attrs, CFStringRef(QAXNextContentsAttribute));
+        qt_mac_append_cf_uniq(attrs, CFStringRef(QAXOrientationAttribute));
+    } else if (mac_role == CFStringRef(QAXScrollAreaRole)) {
+        if (scrollAreaHasScrollBar(interface, Qt::Horizontal))
+            qt_mac_append_cf_uniq(attrs, CFStringRef(QAXHorizontalScrollBarAttribute));
+        if (scrollAreaHasScrollBar(interface, Qt::Vertical))
+            qt_mac_append_cf_uniq(attrs, CFStringRef(QAXVerticalScrollBarAttribute));
+        qt_mac_append_cf_uniq(attrs, CFStringRef(QAXContentsAttribute));
+    } else if (mac_role == CFStringRef(QAXTabGroupRole)) {
+        qt_mac_append_cf_uniq(attrs, CFStringRef(QAXTabsAttribute));
+        // Only tab widgets can have the contents attribute, there is no way of getting
+        // the contents from a QTabBar.
+        if (isTabWidget(interface)) 
+            qt_mac_append_cf_uniq(attrs, CFStringRef(QAXContentsAttribute));
+    }
+
+    return noErr;
+}
+
+static void handleStringAttribute(EventRef event, QAccessible::Text text, const QAInterface &interface)
+{
+    QString str = interface.text(text);
+    if (str.isEmpty())
+        return;
+
+    // Remove any html markup from the text string, or VoiceOver will read the html tags.
+    static QTextDocument document;
+    document.setHtml(str);
+    str = document.toPlainText();
+
+    CFStringRef cfstr = QCFString::toCFStringRef(str);
+    SetEventParameter(event, kEventParamAccessibleAttributeValue, typeCFStringRef, sizeof(cfstr), &cfstr);
+}
+
+/*
+    Handles the parent attribute for a interface.
+    There are basically three cases here:
+    1. interface is a HIView and has only HIView children.
+    2. interface is a HIView but has children that is not a HIView
+    3. interface is not a HIView.
+*/
+static OSStatus handleChildrenAttribute(EventHandlerCallRef next_ref, EventRef event, QAInterface &interface)
+{
+   // Add the children for this interface to the global QAccessibelHierachyManager.
+    accessibleHierarchyManager()->registerChildren(interface);
+
+    if (isTabWidget(interface)) {
+        QList<QAElement> children = tabWidgetGetChildren(interface);
+        const int childCount = children.count();
+
+        CFMutableArrayRef array = 0;
+        array = CFArrayCreateMutable(0, 0, &kCFTypeArrayCallBacks);
+        for (int i = 0; i < childCount; ++i)  {
+            qt_mac_append_cf_uniq(array, children.at(i).element());
+        }
+
+        OSStatus err;
+        err = SetEventParameter(event, kEventParamAccessibleAttributeValue, typeCFArrayRef, sizeof(array), &array);
+        if (err != noErr)
+            qWarning("Qt:Internal error (%s:%d)", __FILE__, __LINE__);
+
+        return noErr;
+    }
+
+    const QList<QAElement> children = lookup(interface.children());
+    const int childCount = children.count();
+
+    OSStatus err = eventNotHandledErr;
+    if (interface.isHIView())
+        err = CallNextEventHandler(next_ref, event);
+
+    CFMutableArrayRef array = 0;
+    int arraySize = 0;
+    if (err == noErr) {
+        CFTypeRef obj = 0;
+        err = GetEventParameter(event, kEventParamAccessibleAttributeValue, typeCFTypeRef, NULL , sizeof(obj), NULL, &obj);
+        if (err == noErr && obj != 0) {
+            array = (CFMutableArrayRef)obj;
+            arraySize = CFArrayGetCount(array);
+        }
+    }
+
+    if (array) {
+        CFArrayRemoveAllValues(array);
+        for (int i = 0; i < childCount; ++i)  {
+            qt_mac_append_cf_uniq(array, children.at(i).element());
+        }
+    } else {
+        array = CFArrayCreateMutable(0, 0, &kCFTypeArrayCallBacks);
+        for (int i = 0; i < childCount; ++i)  {
+            qt_mac_append_cf_uniq(array, children.at(i).element());
+        }
+
+        err = SetEventParameter(event, kEventParamAccessibleAttributeValue, typeCFArrayRef, sizeof(array), &array);
+        if (err != noErr)
+            qWarning("Qt:Internal error (%s:%d)", __FILE__, __LINE__);
+    }
+
+    return noErr;
+}
+
+/*
+
+*/
+static OSStatus handleParentAttribute(EventHandlerCallRef next_ref, EventRef event, const QAInterface &interface)
+{
+    OSStatus err = eventNotHandledErr;
+    if (interface.isHIView()) {
+         err = CallNextEventHandler(next_ref, event);
+    }
+    if (err == noErr)
+        return err;
+
+    const QAInterface parentInterface  = interface.navigate(QAccessible::Ancestor, 1);
+    const QAElement parentElement = accessibleHierarchyManager()->lookup(parentInterface);
+
+    if (parentElement.isValid() == false)
+        return eventNotHandledErr;
+
+    AXUIElementRef elementRef = parentElement.element();
+    SetEventParameter(event, kEventParamAccessibleAttributeValue, typeCFTypeRef, sizeof(elementRef), &elementRef);
+    return noErr;
+}
+#endif
+
+struct IsWindowTest
+{
+    static inline bool test(const QAInterface &interface)
+    {
+        return (interface.role() == QAccessible::Window);
+    }
+};
+
+struct IsWindowAndNotDrawerOrSheetTest
+{
+    static inline bool test(const QAInterface &interface)
+    {
+        QWidget * const widget = qobject_cast<QWidget*>(interface.object());
+        return (interface.role() == QAccessible::Window &&
+                widget && widget->isWindow() &&
+                !qt_mac_is_macdrawer(widget) &&
+                !qt_mac_is_macsheet(widget));
+    }
+};
+
+/*
+    Navigates up the iterfaces ancestor hierachy until a QAccessibleInterface that
+    passes the Test is found. If we reach a interface that is a HIView we stop the
+    search and call AXUIElementCopyAttributeValue.
+*/
+template <typename TestType>
+OSStatus navigateAncestors(EventHandlerCallRef next_ref, EventRef event, const QAInterface &interface, CFStringRef attribute)
+{
+    if (interface.isHIView())
+        return CallNextEventHandler(next_ref, event);
+
+    QAInterface current = interface;
+    QAElement element;
+    while (current.isValid()) {
+        if (TestType::test(interface)) {
+            element = accessibleHierarchyManager()->lookup(current);
+            break;
+        }
+
+        // If we reach an InterfaceItem that is a HiView we can hand of the search to
+        // the system event handler. This is the common case.
+        if (current.isHIView()) {
+            CFTypeRef value = 0;
+            const QAElement currentElement = accessibleHierarchyManager()->lookup(current);
+            AXError err = AXUIElementCopyAttributeValue(currentElement.element(), attribute, &value);
+            AXUIElementRef newElement = (AXUIElementRef)value;
+
+            if (err == noErr)
+                element = QAElement(newElement);
+
+            if (newElement != 0)
+                CFRelease(newElement);
+            break;
+        }
+
+        QAInterface next = current.parent();
+        if (next.isValid() == false)
+            break;
+        if (next == current)
+            break;
+        current = next;
+    }
+
+    if (element.isValid() == false)
+        return eventNotHandledErr;
+
+
+    AXUIElementRef elementRef = element.element();
+    SetEventParameter(event, kEventParamAccessibleAttributeValue, typeCFTypeRef,
+                                      sizeof(elementRef), &elementRef);
+    return noErr;
+}
+
+/*
+    Returns the top-level window for an interface, which is the closest ancestor interface that
+    has the Window role, but is not a sheet or a drawer.
+*/
+#ifndef QT_MAC_USE_COCOA
+static OSStatus handleWindowAttribute(EventHandlerCallRef next_ref, EventRef event, const QAInterface &interface)
+{
+    return navigateAncestors<IsWindowAndNotDrawerOrSheetTest>(next_ref, event, interface, CFStringRef(QAXWindowAttribute));
+}
+
+/*
+    Returns the top-level window for an interface, which is the closest ancestor interface that
+    has the Window role. (Can also be a sheet or a drawer)
+*/
+static OSStatus handleTopLevelUIElementAttribute(EventHandlerCallRef next_ref, EventRef event, const QAInterface &interface)
+{
+    return navigateAncestors<IsWindowTest>(next_ref, event, interface, CFStringRef(QAXTopLevelUIElementAttribute));
+}
+
+/*
+    Returns the tab buttons for an interface.
+*/
+static OSStatus handleTabsAttribute(EventHandlerCallRef next_ref, EventRef event, QAInterface &interface)
+{
+    Q_UNUSED(next_ref);
+    if (isTabWidget(interface))
+        return setAttributeValue(event, tabWidgetGetTabs(interface));
+    else
+        return setAttributeValue(event, tabBarGetTabs(interface));
+}
+
+static OSStatus handlePositionAttribute(EventHandlerCallRef, EventRef event, const QAInterface &interface)
+{
+    QPoint qpoint(interface.rect().topLeft());
+    HIPoint point;
+    point.x = qpoint.x();
+    point.y = qpoint.y();
+    SetEventParameter(event, kEventParamAccessibleAttributeValue, typeHIPoint, sizeof(point), &point);
+    return noErr;
+}
+
+static OSStatus handleSizeAttribute(EventHandlerCallRef, EventRef event, const QAInterface &interface)
+{
+    QSize qSize(interface.rect().size());
+    HISize size;
+    size.width = qSize.width();
+    size.height = qSize.height();
+    SetEventParameter(event, kEventParamAccessibleAttributeValue, typeHISize, sizeof(size), &size);
+    return noErr;
+}
+
+static OSStatus handleSubroleAttribute(EventHandlerCallRef, EventRef event, const QAInterface &interface)
+{
+    const QCFString role = subrole(interface);
+    CFStringRef rolestr = (CFStringRef)role;
+    SetEventParameter(event, kEventParamAccessibleAttributeValue, typeCFTypeRef, sizeof(rolestr), &rolestr);
+    return noErr;
+}
+
+static OSStatus handleOrientationAttribute(EventHandlerCallRef next_ref, EventRef event, const QAInterface &interface)
+{
+    QObject *const object = interface.object();
+    Qt::Orientation orientation;
+    if (interface.role() == QAccessible::ScrollBar) {
+        orientation  = scrollBarOrientation(interface);
+    } else if (QSplitterHandle * const splitter = qobject_cast<QSplitterHandle * const>(object)) {
+        // Qt reports the layout orientation, but we want the splitter handle orientation.
+        orientation = (splitter->orientation() == Qt::Horizontal) ? Qt::Vertical : Qt::Horizontal;
+    } else {
+        return CallNextEventHandler(next_ref, event);
+    }
+    const CFStringRef orientationString = (orientation == Qt::Vertical)
+        ? CFStringRef(QAXVerticalOrientationValue) : CFStringRef(QAXHorizontalOrientationValue);
+    SetEventParameter(event, kEventParamAccessibleAttributeValue, typeCFStringRef, sizeof(orientationString), &orientationString);
+    return noErr;
+}
+
+/*
+    Figures out the next or previous contents for a splitter.
+*/
+static OSStatus handleSplitterContentsAttribute(EventHandlerCallRef next_ref, EventRef event, const QAInterface &interface, QCFString nextOrPrev)
+{
+    if (interface.isValid() == false || interface.role() != QAccessible::Grip)
+        return eventNotHandledErr;
+
+    const QAInterface parent = interface.parent();
+    if (parent.isValid() == false)
+        return CallNextEventHandler(next_ref, event);
+
+    if (parent.role() != QAccessible::Splitter)
+        return CallNextEventHandler(next_ref, event);
+
+    const QSplitter * const splitter = qobject_cast<const QSplitter * const>(parent.object());
+    if (splitter == 0)
+        return CallNextEventHandler(next_ref, event);
+
+    QWidget * const splitterHandle = qobject_cast<QWidget * const>(interface.object());
+    const int splitterHandleIndex = splitter->indexOf(splitterHandle);
+    const int widgetIndex = (nextOrPrev == QCFString(CFStringRef(QAXPreviousContentsAttribute))) ? splitterHandleIndex - 1 : splitterHandleIndex;
+    const QAElement contentsElement = accessibleHierarchyManager()->lookup(splitter->widget(widgetIndex), 0);
+    return setAttributeValue(event, QList<QAElement>() << contentsElement);
+}
+
+/*
+    Creates a list of all splitter handles the splitter contains.
+*/
+static OSStatus handleSplittersAttribute(EventHandlerCallRef next_ref, EventRef event, QAInterface &interface)
+{
+    const QSplitter * const splitter = qobject_cast<const QSplitter * const>(interface.object());
+    if (splitter == 0)
+        return CallNextEventHandler(next_ref, event);
+
+    accessibleHierarchyManager()->registerChildren(interface);
+
+    QList<QAElement> handles;
+    const int visibleSplitterCount = splitter->count() -1; // skip first handle, it's always invisible.
+    for (int i = 0; i < visibleSplitterCount; ++i)
+        handles.append(accessibleHierarchyManager()->lookup(splitter->handle(i + 1), 0));
+
+    return setAttributeValue(event, handles);
+}
+
+// This handler gets the scroll bars for a scroll area
+static OSStatus handleScrollBarAttribute(EventHandlerCallRef next_ref, EventRef event, QAInterface &scrollArea, Qt::Orientation orientation)
+{
+    QAElement scrollBar = scrollAreaGetScrollBar(scrollArea, orientation);
+    if (scrollBar.isValid() == false)
+        return CallNextEventHandler(next_ref, event);
+
+    AXUIElementRef elementRef = scrollBar.element();
+    SetEventParameter(event, kEventParamAccessibleAttributeValue, typeCFTypeRef, sizeof(elementRef), &elementRef);
+    return noErr;
+}
+
+// This handler gets the contents for a scroll area or tab widget.
+static OSStatus handleContentsAttribute(EventHandlerCallRef next_ref, EventRef event, QAInterface &interface)
+{
+    const QCFString mac_role = macRole(interface);
+
+    QAElement contents;
+
+    if (mac_role == kAXTabGroupRole) {
+        contents = tabWidgetGetContents(interface);
+    } else {
+        contents = scrollAreaGetContents(interface);
+        if (contents.isValid() == false)
+            return CallNextEventHandler(next_ref, event);
+    }
+
+    return setAttributeValue(event, QList<QAElement>() << contents);
+}
+
+static OSStatus handleRowsAttribute(EventHandlerCallRef, EventRef event, QAInterface &tableView)
+{
+    QList<QAElement> rows = lookup(tableView.children());
+
+    // kill the first row which is the horizontal header.
+    rows.removeAt(0);
+
+    return setAttributeValue(event, rows);
+}
+
+static OSStatus handleVisibleRowsAttribute(EventHandlerCallRef, EventRef event, QAInterface &tableView)
+{
+    QList<QAElement> visibleRows;
+
+    QList<QAInterface> rows = tableView.children();
+    // kill the first row which is the horizontal header.
+    rows.removeAt(0);
+
+    foreach (const QAInterface &interface, rows)
+        if ((interface.state() & QAccessible::Invisible) == false)
+            visibleRows.append(accessibleHierarchyManager()->lookup(interface));
+
+    return setAttributeValue(event, visibleRows);
+}
+
+static OSStatus handleSelectedRowsAttribute(EventHandlerCallRef, EventRef event, QAInterface &tableView)
+{
+    QList<QAElement> selectedRows;
+    foreach (const QAInterface &interface, tableView.children())
+        if ((interface.state() & QAccessible::Selected))
+            selectedRows.append(accessibleHierarchyManager()->lookup(interface));
+
+    return setAttributeValue(event, selectedRows);
+}
+
+static OSStatus getNamedAttribute(EventHandlerCallRef next_ref, EventRef event, QAInterface &interface)
+{
+    CFStringRef var;
+    GetEventParameter(event, kEventParamAccessibleAttributeName, typeCFStringRef, 0,
+                              sizeof(var), 0, &var);
+
+    if (CFStringCompare(var, CFStringRef(QAXChildrenAttribute), 0) == kCFCompareEqualTo) {
+        return handleChildrenAttribute(next_ref, event, interface);
+    } else if(CFStringCompare(var, CFStringRef(QAXTopLevelUIElementAttribute), 0) == kCFCompareEqualTo) {
+        return handleTopLevelUIElementAttribute(next_ref, event, interface);
+    } else if(CFStringCompare(var, CFStringRef(QAXWindowAttribute), 0) == kCFCompareEqualTo) {
+        return handleWindowAttribute(next_ref, event, interface);
+    } else if(CFStringCompare(var, CFStringRef(QAXParentAttribute), 0) == kCFCompareEqualTo) {
+        return handleParentAttribute(next_ref, event, interface);
+    } else if (CFStringCompare(var, CFStringRef(QAXPositionAttribute), 0) == kCFCompareEqualTo) {
+        return handlePositionAttribute(next_ref, event, interface);
+    } else if (CFStringCompare(var, CFStringRef(QAXSizeAttribute), 0) == kCFCompareEqualTo) {
+        return handleSizeAttribute(next_ref, event, interface);
+    } else  if (CFStringCompare(var, CFStringRef(QAXRoleAttribute), 0) == kCFCompareEqualTo) {
+        CFStringRef role = macRole(interface);
+// ###
+//        QWidget * const widget = qobject_cast<QWidget *>(interface.object());
+//        if (role == CFStringRef(QAXUnknownRole) && widget && widget->isWindow())
+//            role = CFStringRef(QAXWindowRole);
+
+        SetEventParameter(event, kEventParamAccessibleAttributeValue, typeCFStringRef,
+                          sizeof(role), &role);
+
+    } else if (CFStringCompare(var, CFStringRef(QAXEnabledAttribute), 0) == kCFCompareEqualTo) {
+        Boolean val =  !((interface.state() & QAccessible::Unavailable))
+                     && !((interface.state() & QAccessible::Invisible));
+        SetEventParameter(event, kEventParamAccessibleAttributeValue, typeBoolean,
+                          sizeof(val), &val);
+    } else if (CFStringCompare(var, CFStringRef(QAXExpandedAttribute), 0) == kCFCompareEqualTo) {
+        Boolean val = (interface.state() & QAccessible::Expanded);
+        SetEventParameter(event, kEventParamAccessibleAttributeValue, typeBoolean,
+                          sizeof(val), &val);
+    } else if (CFStringCompare(var, CFStringRef(QAXSelectedAttribute), 0) == kCFCompareEqualTo) {
+        Boolean val = (interface.state() & QAccessible::Selection);
+        SetEventParameter(event, kEventParamAccessibleAttributeValue, typeBoolean,
+                          sizeof(val), &val);
+    } else if (CFStringCompare(var, CFStringRef(QAXFocusedAttribute), 0) == kCFCompareEqualTo) {
+        Boolean val = (interface.state() & QAccessible::Focus);
+        SetEventParameter(event, kEventParamAccessibleAttributeValue, typeBoolean,
+                          sizeof(val), &val);
+    } else if (CFStringCompare(var, CFStringRef(QAXSelectedChildrenAttribute), 0) == kCFCompareEqualTo) {
+        const int cc = interface.childCount();
+        QList<QAElement> selected;
+        for (int i = 1; i <= cc; ++i) {
+            const QAInterface child_iface = interface.navigate(QAccessible::Child, i);
+            if (child_iface.isValid() && child_iface.state() & QAccessible::Selected)
+                selected.append(accessibleHierarchyManager()->lookup(child_iface));
+        }
+
+        return setAttributeValue(event, selected);
+
+      } else if (CFStringCompare(var, CFStringRef(QAXCloseButtonAttribute), 0) == kCFCompareEqualTo) {
+        if(interface.object() && interface.object()->isWidgetType()) {
+            Boolean val = true; //do we want to add a WState for this?
+            SetEventParameter(event, kEventParamAccessibleAttributeValue, typeBoolean,
+                              sizeof(val), &val);
+        }
+    } else if (CFStringCompare(var, CFStringRef(QAXZoomButtonAttribute), 0) == kCFCompareEqualTo) {
+        if(interface.object() && interface.object()->isWidgetType()) {
+            QWidget *widget = (QWidget*)interface.object();
+            Boolean val = (widget->windowFlags() & Qt::WindowMaximizeButtonHint);
+            SetEventParameter(event, kEventParamAccessibleAttributeValue, typeBoolean,
+                              sizeof(val), &val);
+        }
+    } else if (CFStringCompare(var, CFStringRef(QAXMinimizeButtonAttribute), 0) == kCFCompareEqualTo) {
+        if(interface.object() && interface.object()->isWidgetType()) {
+            QWidget *widget = (QWidget*)interface.object();
+            Boolean val = (widget->windowFlags() & Qt::WindowMinimizeButtonHint);
+            SetEventParameter(event, kEventParamAccessibleAttributeValue, typeBoolean,
+                              sizeof(val), &val);
+        }
+    } else if (CFStringCompare(var, CFStringRef(QAXToolbarButtonAttribute), 0) == kCFCompareEqualTo) {
+        if(interface.object() && interface.object()->isWidgetType()) {
+            QWidget *widget = (QWidget*)interface.object();
+            Boolean val = qobject_cast<QMainWindow *>(widget) != 0;
+            SetEventParameter(event, kEventParamAccessibleAttributeValue, typeBoolean,
+                              sizeof(val), &val);
+        }
+    } else if (CFStringCompare(var, CFStringRef(QAXGrowAreaAttribute), 0) == kCFCompareEqualTo) {
+        if(interface.object() && interface.object()->isWidgetType()) {
+            Boolean val = true; //do we want to add a WState for this?
+            SetEventParameter(event, kEventParamAccessibleAttributeValue, typeBoolean,
+                              sizeof(val), &val);
+        }
+    } else if (CFStringCompare(var, CFStringRef(QAXMinimizedAttribute), 0) == kCFCompareEqualTo) {
+        if (interface.object() && interface.object()->isWidgetType()) {
+            QWidget *widget = (QWidget*)interface.object();
+            Boolean val = (widget->windowState() & Qt::WindowMinimized);
+            SetEventParameter(event, kEventParamAccessibleAttributeValue, typeBoolean,
+                              sizeof(val), &val);
+        }
+    } else if (CFStringCompare(var, CFStringRef(QAXSubroleAttribute), 0) == kCFCompareEqualTo) {
+        return handleSubroleAttribute(next_ref, event, interface);
+    } else if (CFStringCompare(var, CFStringRef(QAXRoleDescriptionAttribute), 0) == kCFCompareEqualTo) {
+#if !defined(QT_MAC_USE_COCOA)
+        if (HICopyAccessibilityRoleDescription) {
+            const CFStringRef roleDescription = HICopyAccessibilityRoleDescription(macRole(interface), 0);
+            SetEventParameter(event, kEventParamAccessibleAttributeValue, typeCFStringRef,
+                          sizeof(roleDescription), &roleDescription);
+        } else
+#endif
+        {
+            // Just use Qt::Description on 10.3
+            handleStringAttribute(event, QAccessible::Description, interface);
+        }
+    } else if (CFStringCompare(var, CFStringRef(QAXTitleAttribute), 0) == kCFCompareEqualTo) {
+        const QAccessible::Role role = interface.role();
+        const QAccessible::Text text = (QAccessible::Text)textForRoleAndAttribute(role, var);
+        handleStringAttribute(event, text, interface);
+    } else if (CFStringCompare(var, CFStringRef(QAXValueAttribute), 0) == kCFCompareEqualTo) {
+        const QAccessible::Role role = interface.role();
+        const QAccessible::Text text = (QAccessible::Text)textForRoleAndAttribute(role, var);
+        if (role == QAccessible::CheckBox || role == QAccessible::RadioButton) {
+            int value = buttonValue(interface);
+            SetEventParameter(event, kEventParamAccessibleAttributeValue, typeUInt32, sizeof(value), &value);
+        } else {
+            handleStringAttribute(event, text, interface);
+        }
+    } else if (CFStringCompare(var, CFStringRef(QAXDescriptionAttribute), 0) == kCFCompareEqualTo) {
+        const QAccessible::Role role = interface.role();
+        const QAccessible::Text text = (QAccessible::Text)textForRoleAndAttribute(role, var);
+        handleStringAttribute(event, text, interface);
+    } else if (CFStringCompare(var, CFStringRef(QAXLinkedUIElementsAttribute), 0) == kCFCompareEqualTo) {
+        return CallNextEventHandler(next_ref, event);
+    } else if (CFStringCompare(var, CFStringRef(QAXHelpAttribute), 0) == kCFCompareEqualTo) {
+        const QAccessible::Role role = interface.role();
+        const QAccessible::Text text = (QAccessible::Text)textForRoleAndAttribute(role, var);
+        handleStringAttribute(event, text, interface);
+    } else if (CFStringCompare(var, kAXTitleUIElementAttribute, 0) == kCFCompareEqualTo) {
+        return CallNextEventHandler(next_ref, event);
+    } else if (CFStringCompare(var, CFStringRef(QAXTabsAttribute), 0) == kCFCompareEqualTo) {
+        return handleTabsAttribute(next_ref, event, interface);
+    } else if (CFStringCompare(var, CFStringRef(QAXMinValueAttribute), 0) == kCFCompareEqualTo) {
+        // tabs we first go to the tab bar which is child #2.
+        QAInterface tabBarInterface = interface.childAt(2);
+        return handleTabsAttribute(next_ref, event, tabBarInterface);
+    } else if (CFStringCompare(var, CFStringRef(QAXMinValueAttribute), 0) == kCFCompareEqualTo) {
+        if (interface.role() == QAccessible::RadioButton || interface.role() == QAccessible::CheckBox) {
+            uint value = 0;
+            SetEventParameter(event, kEventParamAccessibleAttributeValue, typeUInt32, sizeof(value), &value);
+        } else {
+            return CallNextEventHandler(next_ref, event);
+        }
+    } else if (CFStringCompare(var, CFStringRef(QAXMaxValueAttribute), 0) == kCFCompareEqualTo) {
+        if (interface.role() == QAccessible::RadioButton || interface.role() == QAccessible::CheckBox) {
+            uint value = 2;
+            SetEventParameter(event, kEventParamAccessibleAttributeValue, typeUInt32, sizeof(value), &value);
+        } else {
+            return CallNextEventHandler(next_ref, event);
+        }
+    } else if (CFStringCompare(var, CFStringRef(QAXOrientationAttribute), 0) == kCFCompareEqualTo) {
+        return handleOrientationAttribute(next_ref, event, interface);
+    } else if (CFStringCompare(var, CFStringRef(QAXPreviousContentsAttribute), 0) == kCFCompareEqualTo) {
+        return handleSplitterContentsAttribute(next_ref, event, interface, CFStringRef(QAXPreviousContentsAttribute));
+    } else if (CFStringCompare(var, CFStringRef(QAXNextContentsAttribute), 0) == kCFCompareEqualTo) {
+        return handleSplitterContentsAttribute(next_ref, event, interface, CFStringRef(QAXNextContentsAttribute));
+    } else if (CFStringCompare(var, CFStringRef(QAXSplittersAttribute), 0) == kCFCompareEqualTo) {
+        return handleSplittersAttribute(next_ref, event, interface);
+    } else if (CFStringCompare(var, CFStringRef(QAXHorizontalScrollBarAttribute), 0) == kCFCompareEqualTo) {
+        return handleScrollBarAttribute(next_ref, event, interface, Qt::Horizontal);
+    } else if (CFStringCompare(var, CFStringRef(QAXVerticalScrollBarAttribute), 0) == kCFCompareEqualTo) {
+        return handleScrollBarAttribute(next_ref, event, interface, Qt::Vertical);
+    } else if (CFStringCompare(var, CFStringRef(QAXContentsAttribute), 0) == kCFCompareEqualTo) {
+        return handleContentsAttribute(next_ref, event, interface);
+    } else if (CFStringCompare(var, CFStringRef(QAXRowsAttribute), 0) == kCFCompareEqualTo) {
+        return handleRowsAttribute(next_ref, event, interface);
+    } else if (CFStringCompare(var, CFStringRef(QAXVisibleRowsAttribute), 0) == kCFCompareEqualTo) {
+        return handleVisibleRowsAttribute(next_ref, event, interface);
+    } else if (CFStringCompare(var, CFStringRef(QAXSelectedRowsAttribute), 0) == kCFCompareEqualTo) {
+        return handleSelectedRowsAttribute(next_ref, event, interface);
+    } else {
+        return CallNextEventHandler(next_ref, event);
+    }
+    return noErr;
+}
+
+static OSStatus isNamedAttributeSettable(EventRef event, const QAInterface &interface)
+{
+    CFStringRef var;
+    GetEventParameter(event, kEventParamAccessibleAttributeName, typeCFStringRef, 0,
+                      sizeof(var), 0, &var);
+    Boolean settable = false;
+    if (CFStringCompare(var, CFStringRef(QAXFocusedAttribute), 0) == kCFCompareEqualTo) {
+        settable = true;
+    } else {
+        for (int r = 0; text_bindings[r][0].qt != -1; r++) {
+            if(interface.role() == (QAccessible::Role)text_bindings[r][0].qt) {
+                for (int a = 1; text_bindings[r][a].qt != -1; a++) {
+                    if (CFStringCompare(var, CFStringRef(text_bindings[r][a].mac), 0) == kCFCompareEqualTo) {
+                        settable = text_bindings[r][a].settable;
+                        break;
+                    }
+                }
+            }
+        }
+    }
+    SetEventParameter(event, kEventParamAccessibleAttributeSettable, typeBoolean,
+                      sizeof(settable), &settable);
+    return noErr;
+}
+
+static OSStatus getChildAtPoint(EventHandlerCallRef next_ref, EventRef event, QAInterface &interface)
+{
+    Q_UNUSED(next_ref);
+    if (interface.isValid() == false)
+        return eventNotHandledErr;
+
+    // Add the children for this interface to the global QAccessibelHierachyManager.
+    accessibleHierarchyManager()->registerChildren(interface);
+
+    Point where;
+    GetEventParameter(event, kEventParamMouseLocation, typeQDPoint, 0, sizeof(where), 0, &where);
+    const QAInterface childInterface = interface.childAt(where.h, where.v);
+
+    if (childInterface.isValid() == false || childInterface == interface)
+        return eventNotHandledErr;
+
+    const QAElement element = accessibleHierarchyManager()->lookup(childInterface);
+    if (element.isValid() == false)
+        return eventNotHandledErr;
+
+    AXUIElementRef elementRef = element.element();
+    CFRetain(elementRef);
+    SetEventParameter(event, kEventParamAccessibleChild, typeCFTypeRef,
+                                  sizeof(elementRef), &elementRef);
+
+    return noErr;
+}
+
+/*
+    Returns a list of actions the given interface supports.
+    Currently implemented by getting the interface role and deciding based on that.
+*/
+static QList<QAccessible::Action> supportedPredefinedActions(const QAInterface &interface)
+{
+    QList<QAccessible::Action> actions;
+    switch (interface.role()) {
+        default:
+            // Most things can be pressed.
+            actions.append(QAccessible::Press);
+        break;
+    }
+
+    return actions;
+}
+
+/*
+    Translates a predefined QAccessible::Action to a Mac action constant.
+    Returns an empty string if the Qt Action has no mac equivalent.
+*/
+static QCFString translateAction(const QAccessible::Action action)
+{
+    switch (action) {
+        case QAccessible::Press:
+            return CFStringRef(QAXPressAction);
+        break;
+        case QAccessible::Increase:
+            return CFStringRef(QAXIncrementAction);
+        break;
+        case QAccessible::Decrease:
+            return CFStringRef(QAXDecrementAction);
+        break;
+        case QAccessible::Accept:
+            return CFStringRef(QAXConfirmAction);
+        break;
+        case QAccessible::Select:
+            return CFStringRef(QAXPickAction);
+        break;
+        case QAccessible::Cancel:
+            return CFStringRef(QAXCancelAction);
+        break;
+        default:
+            return QCFString();
+        break;
+    }
+}
+
+/*
+    Translates between a Mac action constant and a QAccessible::Action.
+    Returns QAccessible::Default action if there is no Qt predefined equivalent.
+*/
+static QAccessible::Action translateAction(const CFStringRef actionName)
+{
+    if(CFStringCompare(actionName, CFStringRef(QAXPressAction), 0) == kCFCompareEqualTo) {
+        return QAccessible::Press;
+    } else if(CFStringCompare(actionName, CFStringRef(QAXIncrementAction), 0) == kCFCompareEqualTo) {
+        return QAccessible::Increase;
+    } else if(CFStringCompare(actionName, CFStringRef(QAXDecrementAction), 0) == kCFCompareEqualTo) {
+        return QAccessible::Decrease;
+    } else if(CFStringCompare(actionName, CFStringRef(QAXConfirmAction), 0) == kCFCompareEqualTo) {
+        return QAccessible::Accept;
+    } else if(CFStringCompare(actionName, CFStringRef(QAXPickAction), 0) == kCFCompareEqualTo) {
+        return QAccessible::Select;
+    } else if(CFStringCompare(actionName, CFStringRef(QAXCancelAction), 0) == kCFCompareEqualTo) {
+        return QAccessible::Cancel;
+    } else {
+        return QAccessible::DefaultAction;
+    }
+}
+#endif // QT_MAC_USE_COCOA
+
+/*
+    Copies the translated names all supported actions for an interface into the kEventParamAccessibleActionNames
+    event parameter.
+*/
+#ifndef QT_MAC_USE_COCOA
+static OSStatus getAllActionNames(EventHandlerCallRef next_ref, EventRef event, const QAInterface &interface)
+{
+    Q_UNUSED(next_ref);
+
+    CFMutableArrayRef actions = 0;
+    GetEventParameter(event, kEventParamAccessibleActionNames, typeCFMutableArrayRef, 0,
+                      sizeof(actions), 0, &actions);
+
+    // Add supported predefined actions.
+    const QList<QAccessible::Action> predefinedActions = supportedPredefinedActions(interface);
+    for (int i = 0; i < predefinedActions.count(); ++i) {
+        const QCFString action = translateAction(predefinedActions.at(i));
+        if (action != QCFString())
+            qt_mac_append_cf_uniq(actions, action);
+    }
+
+    // Add user actions
+    const int actionCount = interface.userActionCount();
+    for (int i = 0; i < actionCount; ++i) {
+        const QString actionName = interface.actionText(i, QAccessible::Name);
+        qt_mac_append_cf_uniq(actions, QCFString::toCFStringRef(actionName));
+    }
+
+    return noErr;
+}
+#endif
+
+/*
+    Handles the perforNamedAction event.
+*/
+#ifndef QT_MAC_USE_COCOA
+static OSStatus performNamedAction(EventHandlerCallRef next_ref, EventRef event, const QAInterface& interface)
+{
+    Q_UNUSED(next_ref);
+
+    CFStringRef act;
+    GetEventParameter(event, kEventParamAccessibleActionName, typeCFStringRef, 0,
+                      sizeof(act), 0, &act);
+
+    const QAccessible::Action action = translateAction(act);
+
+    // Perform built-in action
+    if (action != QAccessible::DefaultAction) {
+        interface.doAction(action, QVariantList());
+        return noErr;
+    }
+
+    // Search for user-defined actions and perform it if found.
+    const int actCount = interface.userActionCount();
+    const QString qAct = QCFString::toQString(act);
+    for(int i = 0; i < actCount; i++) {
+        if(interface.actionText(i, QAccessible::Name) == qAct) {
+            interface.doAction(i, QVariantList());
+            break;
+        }
+    }
+    return noErr;
+}
+
+static OSStatus setNamedAttribute(EventHandlerCallRef next_ref, EventRef event, const QAInterface &interface)
+{
+    Q_UNUSED(next_ref);
+    Q_UNUSED(event);
+
+    CFStringRef var;
+    GetEventParameter(event, kEventParamAccessibleAttributeName, typeCFStringRef, 0,
+                      sizeof(var), 0, &var);
+    if(CFStringCompare(var, CFStringRef(QAXFocusedAttribute), 0) == kCFCompareEqualTo) {
+        CFTypeRef val;
+        if(GetEventParameter(event, kEventParamAccessibleAttributeValue, typeCFTypeRef, 0,
+                             sizeof(val), 0, &val) == noErr) {
+            if(CFGetTypeID(val) == CFBooleanGetTypeID() &&
+               CFEqual(static_cast<CFBooleanRef>(val), kCFBooleanTrue)) {
+                interface.doAction(QAccessible::SetFocus);
+            }
+        }
+    } else {
+        bool found = false;
+        for(int r = 0; text_bindings[r][0].qt != -1; r++) {
+            if(interface.role() == (QAccessible::Role)text_bindings[r][0].qt) {
+                for(int a = 1; text_bindings[r][a].qt != -1; a++) {
+                    if(CFStringCompare(var, CFStringRef(text_bindings[r][a].mac), 0) == kCFCompareEqualTo) {
+                        if(!text_bindings[r][a].settable) {
+                        } else {
+                            CFTypeRef val;
+                            if(GetEventParameter(event, kEventParamAccessibleAttributeValue, typeCFTypeRef, 0,
+                                                 sizeof(val), 0, &val) == noErr) {
+                                if(CFGetTypeID(val) == CFStringGetTypeID())
+                                    interface.setText((QAccessible::Text)text_bindings[r][a].qt,
+                                                   QCFString::toQString(static_cast<CFStringRef>(val)));
+
+                            }
+                        }
+                        found = true;
+                        break;
+                    }
+                }
+                break;
+            }
+        }
+    }
+    return noErr;
+}
+
+/*
+    This is the main accessibility event handler.
+*/
+static OSStatus accessibilityEventHandler(EventHandlerCallRef next_ref, EventRef event, void *data)
+{
+    Q_UNUSED(data)
+
+    // Return if this event is not a AccessibleGetNamedAttribute event.
+    const UInt32 eclass = GetEventClass(event);
+    if (eclass != kEventClassAccessibility)
+        return eventNotHandledErr;
+
+    // Get the AXUIElementRef and QAInterface pointer
+    AXUIElementRef element = 0;
+    GetEventParameter(event, kEventParamAccessibleObject, typeCFTypeRef, 0, sizeof(element), 0, &element);
+    QAInterface interface = accessibleHierarchyManager()->lookup(element);
+    if (interface.isValid() == false)
+        return eventNotHandledErr;
+
+    const UInt32 ekind = GetEventKind(event);
+    OSStatus status = noErr;
+    switch (ekind) {
+        case kEventAccessibleGetAllAttributeNames:
+             status = getAllAttributeNames(event, interface, next_ref);
+        break;
+        case kEventAccessibleGetNamedAttribute:
+             status = getNamedAttribute(next_ref, event, interface);
+        break;
+        case kEventAccessibleIsNamedAttributeSettable:
+             status = isNamedAttributeSettable(event, interface);
+        break;
+        case kEventAccessibleGetChildAtPoint:
+            status = getChildAtPoint(next_ref, event, interface);
+        break;
+        case kEventAccessibleGetAllActionNames:
+            status = getAllActionNames(next_ref, event, interface);
+        break;
+        case kEventAccessibleGetFocusedChild:
+            status = CallNextEventHandler(next_ref, event);
+        break;
+        case kEventAccessibleSetNamedAttribute:
+            status = setNamedAttribute(next_ref, event, interface);
+        break;
+        case kEventAccessiblePerformNamedAction:
+            status = performNamedAction(next_ref, event, interface);
+        break;
+        default:
+            status = CallNextEventHandler(next_ref, event);
+        break;
+    };
+    return status;
+}
+#endif
+
+void QAccessible::initialize()
+{
+#ifndef QT_MAC_USE_COCOA
+    registerQtAccessibilityHIObjectSubclass();
+    installApplicationEventhandler();
+#endif
+}
+
+// Sets thre root object for the application
+void QAccessible::setRootObject(QObject *object)
+{
+    // Call installed root object handler if we have one
+    if (rootObjectHandler) {
+        rootObjectHandler(object);
+        return;
+    }
+
+    rootObject = object;
+}
+
+void QAccessible::cleanup()
+{
+    accessibleHierarchyManager()->reset();
+#ifndef QT_MAC_USE_COCOA
+    removeEventhandler(applicationEventHandlerUPP);
+    removeEventhandler(objectCreateEventHandlerUPP);
+    removeEventhandler(accessibilityEventHandlerUPP);
+#endif
+}
+
+void QAccessible::updateAccessibility(QObject *object, int child, Event reason)
+{
+    // Call installed update handler if we have one.
+    if (updateHandler) {
+        updateHandler(object, child, reason);
+        return;
+    }
+
+#ifndef QT_MAC_USE_COCOA
+    // Return if the mac accessibility is not enabled.
+    if(!AXAPIEnabled())
+        return;
+
+     // Work around crash, disable accessiblity for focus frames.
+     if (qstrcmp(object->metaObject()->className(), "QFocusFrame") == 0)
+        return;
+
+//    qDebug() << "updateAccessibility" << object << child << hex << reason;
+
+    if (reason == ObjectShow) {
+        QAInterface interface = QAInterface(QAccessible::queryAccessibleInterface(object), child);
+        accessibleHierarchyManager()->registerInterface(interface);
+    }
+
+    const QAElement element = accessibleHierarchyManager()->lookup(object, child);
+    if (element.isValid() == false)
+        return;
+
+
+    CFStringRef notification = 0;
+    if(object && object->isWidgetType() && reason == ObjectCreated) {
+        notification = CFStringRef(QAXWindowCreatedNotification);
+    } else if(reason == ValueChanged) {
+        notification = CFStringRef(QAXValueChangedNotification);
+    } else if(reason == MenuStart) {
+        notification = CFStringRef(QAXMenuOpenedNotification);
+    } else if(reason == MenuEnd) {
+        notification = CFStringRef(QAXMenuClosedNotification);
+    } else if(reason == LocationChanged) {
+        notification = CFStringRef(QAXWindowMovedNotification);
+    } else if(reason == ObjectShow || reason == ObjectHide ) {
+        // When a widget is deleted we get a ObjectHide before the destroyed(QObject *)
+        // signal is emitted (which makes sense). However, at this point we are in the
+        // middle of the QWidget destructor which means that we have to be careful when
+        // using the widget pointer. Since we can't control what the accessibilty interfaces
+        // does when navigate() is called below we ignore the hide update in this case.
+        // (the widget will be deleted soon anyway.)
+        extern QWidgetPrivate * qt_widget_private(QWidget *);
+        if (QWidget *widget = qobject_cast<QWidget*>(object)) {
+            if (qt_widget_private(widget)->data.in_destructor)
+                return;
+
+            // Check widget parent as well, special case for preventing crash
+            // when the viewport() of an abstract scroll area is hidden when
+            // the QWidget destructor hides all its children.
+            QWidget *parentWidget = widget->parentWidget();
+            if (parentWidget && qt_widget_private(parentWidget)->data.in_destructor)
+                return;
+        }
+
+        // There is no equivalent Mac notification for ObjectShow/Hide, so we call HIObjectSetAccessibilityIgnored
+        // and isItIntersting which will mark the HIObject accociated with the element as ignored if the
+        // QAccessible::Invisible state bit is set.
+        QAInterface interface = accessibleHierarchyManager()->lookup(element);
+        if (interface.isValid()) {
+            HIObjectSetAccessibilityIgnored(element.object(), !isItInteresting(interface));
+        }
+
+        // If the interface manages its own children, also check if we should ignore those.
+        if (isItemView(interface) == false && managesChildren(interface)) {
+            for (int i = 1; i <= interface.childCount(); ++i) {
+                QAInterface childInterface = interface.navigate(QAccessible::Child, i);
+                if (childInterface.isValid() && childInterface.isHIView() == false) {
+                    const QAElement element = accessibleHierarchyManager()->lookup(childInterface);
+                    if (element.isValid()) {
+                        HIObjectSetAccessibilityIgnored(element.object(), !isItInteresting(childInterface));
+                    }
+                }
+            }
+        }
+
+    } else if(reason == Focus) {
+        if(object && object->isWidgetType()) {
+            QWidget *w = static_cast<QWidget*>(object);
+            if(w->isWindow())
+                notification = CFStringRef(QAXFocusedWindowChangedNotification);
+            else
+                notification = CFStringRef(QAXFocusedUIElementChangedNotification);
+        }
+    }
+
+    if (!notification)
+        return;
+
+    AXNotificationHIObjectNotify(notification, element.object(), element.id());
+#endif
+}
+
+QT_END_NAMESPACE
+
+#endif // QT_NO_ACCESSIBILITY