summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorMorten Sorvig <morten.sorvig@nokia.com>2011-10-11 11:04:59 +0200
committerQt by Nokia <qt-info@nokia.com>2011-10-19 03:04:40 +0200
commit946805f07f9f8270d60df58f07bd8836b76d7258 (patch)
treec9b6901a509d456d0d71784034640f6f1063b32f /src
parentd884f24fe1b86bbd71d62584d5cf1381355efe0d (diff)
Cocoa: Add initial accessibility implementation.
See qcocoaaccessiblity.h for details. For now only the first level of the hierarchy is made accessible. Also add tools/accessibilityinspector which is an utility for inspecting and debugging the Qt accessibility tree. Change-Id: Iff520bec26b3761feb0c2e00471feb379daaa735 Reviewed-by: Morten Johan Sørvig <morten.sorvig@nokia.com>
Diffstat (limited to 'src')
-rw-r--r--src/plugins/platforms/cocoa/cocoa.pro9
-rw-r--r--src/plugins/platforms/cocoa/qcocoaaccessibility.h68
-rw-r--r--src/plugins/platforms/cocoa/qcocoaaccessibility.mm113
-rw-r--r--src/plugins/platforms/cocoa/qcocoaaccessibilityelement.h65
-rw-r--r--src/plugins/platforms/cocoa/qcocoaaccessibilityelement.mm197
-rw-r--r--src/plugins/platforms/cocoa/qnsview.h2
-rw-r--r--src/plugins/platforms/cocoa/qnsview.mm32
-rw-r--r--src/plugins/platforms/cocoa/qnsviewaccessibility.mm117
8 files changed, 599 insertions, 4 deletions
diff --git a/src/plugins/platforms/cocoa/cocoa.pro b/src/plugins/platforms/cocoa/cocoa.pro
index 40d3323819..80149ae8d2 100644
--- a/src/plugins/platforms/cocoa/cocoa.pro
+++ b/src/plugins/platforms/cocoa/cocoa.pro
@@ -7,6 +7,7 @@ OBJECTIVE_SOURCES += main.mm \
qcocoabackingstore.mm \
qcocoawindow.mm \
qnsview.mm \
+ qnsviewaccessibility.mm \
qcocoaautoreleasepool.mm \
qnswindowdelegate.mm \
qcocoaglcontext.mm \
@@ -19,6 +20,8 @@ OBJECTIVE_SOURCES += main.mm \
qmenu_mac.mm \
qcocoahelpers.mm \
qmultitouch_mac.mm \
+ qcocoaaccessibilityelement.mm \
+ qcocoaaccessibility.mm \
HEADERS += qcocoaintegration.h \
qcocoabackingstore.h \
@@ -36,6 +39,8 @@ HEADERS += qcocoaintegration.h \
qmenu_mac.h \
qcocoahelpers.h \
qmultitouch_mac_p.h \
+ qcocoaaccessibilityelement.h \
+ qcocoaaccessibility.h \
RESOURCES += qcocoaresources.qrc
@@ -47,3 +52,7 @@ QT += core-private gui-private widgets-private platformsupport-private
CONFIG += qpa/basicunixfontdatabase
target.path += $$[QT_INSTALL_PLUGINS]/platforms
INSTALLS += target
+
+# Acccessibility debug support
+# DEFINES += QT_COCOA_ENABLE_ACCESSIBILITY_INSPECTOR
+# include ($$PWD/../../../../tools/accessibilityinspector/accessibilityinspector.pri)
diff --git a/src/plugins/platforms/cocoa/qcocoaaccessibility.h b/src/plugins/platforms/cocoa/qcocoaaccessibility.h
new file mode 100644
index 0000000000..7f4a840b15
--- /dev/null
+++ b/src/plugins/platforms/cocoa/qcocoaaccessibility.h
@@ -0,0 +1,68 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** 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.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#ifndef QCOCOAACCESIBILITY_H
+#define QCOCOAACCESIBILITY_H
+
+#include <Cocoa/Cocoa.h>
+
+#include <QtGui>
+
+/*
+ Qt Cocoa Accessibility Overview
+
+ Cocoa accessibility is implemented in the following files:
+
+ - qnsviewaccessibility : Root accessibility implementation for QNSView
+ - qcocoaaccessibilityelement : Cocoa accessibility protocol wrapper for QAccessibleInterface
+ - qcocoaaccessibility (this file) : Conversion and helper functions.
+
+ The accessibility implementation wraps QAccessibleInterfaces in QCocoaAccessibleElements, which
+ implements the cocoa accessibility protocol. The root QAccessibleInterface (the one returned
+ by QWindow::accessibleRoot), is anchored to the QNSView in qnsviewaccessibility.mm.
+
+ Cocoa explores the accessibility tree by walking the tree using the parent/child
+ relationships or hit testing. When this happens we create QCocoaAccessibleElements on
+ demand.
+*/
+
+NSString *macRole(QAccessible::Role);
+
+#endif
diff --git a/src/plugins/platforms/cocoa/qcocoaaccessibility.mm b/src/plugins/platforms/cocoa/qcocoaaccessibility.mm
new file mode 100644
index 0000000000..a2ce743804
--- /dev/null
+++ b/src/plugins/platforms/cocoa/qcocoaaccessibility.mm
@@ -0,0 +1,113 @@
+/****************************************************************************
+ **
+ ** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+ ** All rights reserved.
+ ** Contact: Nokia Corporation (qt-info@nokia.com)
+ **
+ ** This file is part of the plugins of the Qt Toolkit.
+ **
+ ** $QT_BEGIN_LICENSE:LGPL$
+ ** GNU Lesser General Public License Usage
+ ** 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.
+ **
+ ** GNU General Public License Usage
+ ** Alternatively, this file may be used under the terms of the GNU General
+ ** Public License version 3.0 as published by the Free Software Foundation
+ ** and appearing in the file LICENSE.GPL included in the packaging of this
+ ** file. Please review the following information to ensure the GNU General
+ ** Public License version 3.0 requirements will be met:
+ ** http://www.gnu.org/copyleft/gpl.html.
+ **
+ ** Other Usage
+ ** Alternatively, this file may be used in accordance with the terms and
+ ** conditions contained in a signed written agreement between you and Nokia.
+ **
+ **
+ **
+ **
+ **
+ ** $QT_END_LICENSE$
+ **
+ ****************************************************************************/
+#include "qcocoaaccessibility.h"
+
+typedef QMap<QAccessible::Role, NSString *> QMacAccessibiltyRoleMap;
+Q_GLOBAL_STATIC(QMacAccessibiltyRoleMap, qMacAccessibiltyRoleMap);
+
+static void populateRoleMap()
+{
+ QMacAccessibiltyRoleMap &roleMap = *qMacAccessibiltyRoleMap();
+ roleMap[QAccessible::MenuItem] = NSAccessibilityMenuItemRole;
+ roleMap[QAccessible::MenuBar] = NSAccessibilityMenuBarRole;
+ roleMap[QAccessible::ScrollBar] = NSAccessibilityScrollBarRole;
+ roleMap[QAccessible::Grip] = NSAccessibilityGrowAreaRole;
+ roleMap[QAccessible::Window] = NSAccessibilityWindowRole;
+ roleMap[QAccessible::Dialog] = NSAccessibilityWindowRole;
+ roleMap[QAccessible::AlertMessage] = NSAccessibilityWindowRole;
+ roleMap[QAccessible::ToolTip] = NSAccessibilityWindowRole;
+ roleMap[QAccessible::HelpBalloon] = NSAccessibilityWindowRole;
+ roleMap[QAccessible::PopupMenu] = NSAccessibilityMenuRole;
+ roleMap[QAccessible::Application] = NSAccessibilityApplicationRole;
+ roleMap[QAccessible::Pane] = NSAccessibilityGroupRole;
+ roleMap[QAccessible::Grouping] = NSAccessibilityGroupRole;
+ roleMap[QAccessible::Separator] = NSAccessibilitySplitterRole;
+ roleMap[QAccessible::ToolBar] = NSAccessibilityToolbarRole;
+ roleMap[QAccessible::PageTab] = NSAccessibilityRadioButtonRole;
+ roleMap[QAccessible::ButtonMenu] = NSAccessibilityMenuButtonRole;
+ roleMap[QAccessible::ButtonDropDown] = NSAccessibilityPopUpButtonRole;
+ roleMap[QAccessible::SpinBox] = NSAccessibilityIncrementorRole;
+ roleMap[QAccessible::Slider] = NSAccessibilitySliderRole;
+ roleMap[QAccessible::ProgressBar] = NSAccessibilityProgressIndicatorRole;
+ roleMap[QAccessible::ComboBox] = NSAccessibilityPopUpButtonRole;
+ roleMap[QAccessible::RadioButton] = NSAccessibilityRadioButtonRole;
+ roleMap[QAccessible::CheckBox] = NSAccessibilityCheckBoxRole;
+ roleMap[QAccessible::StaticText] = NSAccessibilityStaticTextRole;
+ roleMap[QAccessible::Table] = NSAccessibilityTableRole;
+ roleMap[QAccessible::StatusBar] = NSAccessibilityStaticTextRole;
+ roleMap[QAccessible::Column] = NSAccessibilityColumnRole;
+ roleMap[QAccessible::ColumnHeader] = NSAccessibilityColumnRole;
+ roleMap[QAccessible::Row] = NSAccessibilityRowRole;
+ roleMap[QAccessible::RowHeader] = NSAccessibilityRowRole;
+ roleMap[QAccessible::Cell] = NSAccessibilityTextFieldRole;
+ roleMap[QAccessible::PushButton] = NSAccessibilityButtonRole;
+ roleMap[QAccessible::EditableText] = NSAccessibilityTextFieldRole;
+ roleMap[QAccessible::Link] = NSAccessibilityTextFieldRole;
+ roleMap[QAccessible::Indicator] = NSAccessibilityValueIndicatorRole;
+ roleMap[QAccessible::Splitter] = NSAccessibilitySplitGroupRole;
+ roleMap[QAccessible::List] = NSAccessibilityListRole;
+ roleMap[QAccessible::ListItem] = NSAccessibilityStaticTextRole;
+ roleMap[QAccessible::Cell] = NSAccessibilityStaticTextRole;
+ roleMap[QAccessible::Client] = NSAccessibilityGroupRole;
+}
+
+/*
+ Returns a Mac accessibility role for the given interface, or
+ NSAccessibilityUnknownRole if no role mapping is found.
+*/
+NSString *macRole(QAccessible::Role qtRole)
+{
+ QMacAccessibiltyRoleMap &roleMap = *qMacAccessibiltyRoleMap();
+
+ if (roleMap.isEmpty())
+ populateRoleMap();
+
+ // MAC_ACCESSIBILTY_DEBUG() << "role for" << interface.object() << "interface role" << hex << qtRole;
+
+ if (roleMap.contains(qtRole)) {
+ // MAC_ACCESSIBILTY_DEBUG() << "return" << roleMap[qtRole];
+ return roleMap[qtRole];
+ }
+
+ // MAC_ACCESSIBILTY_DEBUG() << "return NSAccessibilityUnknownRole";
+ return NSAccessibilityUnknownRole;
+}
+
diff --git a/src/plugins/platforms/cocoa/qcocoaaccessibilityelement.h b/src/plugins/platforms/cocoa/qcocoaaccessibilityelement.h
new file mode 100644
index 0000000000..76509f9e43
--- /dev/null
+++ b/src/plugins/platforms/cocoa/qcocoaaccessibilityelement.h
@@ -0,0 +1,65 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** 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.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#ifndef QCOCOAACCESIBILITYELEMENT_H
+#define QCOCOAACCESIBILITYELEMENT_H
+
+
+#import <Cocoa/Cocoa.h>
+#import <AppKit/NSAccessibility.h>
+
+@class QCocoaAccessibleElement;
+
+@interface QCocoaAccessibleElement : NSObject {
+ NSUInteger index;
+ NSString *role;
+ NSObject * parent;
+ void *accessibleInterface;
+
+}
+
+- (id)initWithIndex:(int)aIndex parent:(id)aParent accessibleInterface:(void *)anQAccessibleInterface;
++ (QCocoaAccessibleElement *)elementWithIndex:(int)aIndex parent:(id)aParent accessibleInterface:(void *)anQAccessibleInterface;
+- (NSUInteger)index;
+
+@end
+
+#endif
+
diff --git a/src/plugins/platforms/cocoa/qcocoaaccessibilityelement.mm b/src/plugins/platforms/cocoa/qcocoaaccessibilityelement.mm
new file mode 100644
index 0000000000..4ce41307e7
--- /dev/null
+++ b/src/plugins/platforms/cocoa/qcocoaaccessibilityelement.mm
@@ -0,0 +1,197 @@
+/****************************************************************************
+ **
+ ** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+ ** All rights reserved.
+ ** Contact: Nokia Corporation (qt-info@nokia.com)
+ **
+ ** This file is part of the plugins of the Qt Toolkit.
+ **
+ ** $QT_BEGIN_LICENSE:LGPL$
+ ** GNU Lesser General Public License Usage
+ ** 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.
+ **
+ ** GNU General Public License Usage
+ ** Alternatively, this file may be used under the terms of the GNU General
+ ** Public License version 3.0 as published by the Free Software Foundation
+ ** and appearing in the file LICENSE.GPL included in the packaging of this
+ ** file. Please review the following information to ensure the GNU General
+ ** Public License version 3.0 requirements will be met:
+ ** http://www.gnu.org/copyleft/gpl.html.
+ **
+ ** Other Usage
+ ** Alternatively, this file may be used in accordance with the terms and
+ ** conditions contained in a signed written agreement between you and Nokia.
+ **
+ **
+ **
+ **
+ **
+ ** $QT_END_LICENSE$
+ **
+ ****************************************************************************/
+#include "qcocoaaccessibilityelement.h"
+#include "qcocoaaccessibility.h"
+#include "qcocoahelpers.h"
+
+#include <QAccessible>
+#include "QAccessibleActionInterface"
+
+#import <AppKit/NSAccessibility.h>
+
+static QAccessibleInterface *acast(void *ptr)
+{
+ return reinterpret_cast<QAccessibleInterface *>(ptr);
+}
+
+@implementation QCocoaAccessibleElement
+
+- (id)initWithIndex:(int)aIndex parent:(id)aParent accessibleInterface:(void *)anQAccessibleInterface
+{
+ self = [super init];
+ if (self) {
+ index = aIndex;
+ accessibleInterface = anQAccessibleInterface;
+ role = macRole(acast(accessibleInterface)->role());
+ parent = aParent;
+
+ }
+
+ return self;
+}
+
++ (QCocoaAccessibleElement *)elementWithIndex:(int)aIndex parent:(id)aParent accessibleInterface:(void *)anQAccessibleInterface
+{
+ return [[[self alloc] initWithIndex:aIndex parent:aParent accessibleInterface:anQAccessibleInterface] autorelease];
+}
+
+- (void)dealloc {
+ [super dealloc];
+}
+
+- (BOOL)isEqual:(id)object {
+ if ([object isKindOfClass:[QCocoaAccessibleElement class]]) {
+ QCocoaAccessibleElement *other = object;
+ return (index == other->index) && [role isEqualToString:other->role] && [parent isEqual:other->parent];
+ } else
+ return NO;
+}
+
+- (NSUInteger)hash {
+ return [parent hash] + index;
+}
+
+- (NSUInteger)index {
+ return index;
+}
+
+//
+// accessibility protocol
+//
+
+// attributes
+
+- (NSArray *)accessibilityAttributeNames {
+ static NSArray *attributes = nil;
+ if (attributes == nil) {
+ attributes = [[NSArray alloc] initWithObjects:
+ NSAccessibilityRoleAttribute,
+ NSAccessibilityRoleDescriptionAttribute,
+ NSAccessibilityFocusedAttribute,
+ NSAccessibilityParentAttribute,
+ NSAccessibilityWindowAttribute,
+ NSAccessibilityTopLevelUIElementAttribute,
+ NSAccessibilityPositionAttribute,
+ NSAccessibilitySizeAttribute,
+ NSAccessibilityDescriptionAttribute,
+ nil];
+ }
+ return attributes;
+}
+
+- (id)accessibilityAttributeValue:(NSString *)attribute {
+ if ([attribute isEqualToString:NSAccessibilityRoleAttribute]) {
+ return role;
+ } else if ([attribute isEqualToString:NSAccessibilityRoleDescriptionAttribute]) {
+ return NSAccessibilityRoleDescription(role, nil);
+ } else if ([attribute isEqualToString:NSAccessibilityFocusedAttribute]) {
+ // Just check if the app thinks we're focused.
+ id focusedElement = [NSApp accessibilityAttributeValue:NSAccessibilityFocusedUIElementAttribute];
+ return [NSNumber numberWithBool:[focusedElement isEqual:self]];
+ } else if ([attribute isEqualToString:NSAccessibilityParentAttribute]) {
+ return NSAccessibilityUnignoredAncestor(parent);
+ } else if ([attribute isEqualToString:NSAccessibilityWindowAttribute]) {
+ // We're in the same window as our parent.
+ return [parent accessibilityAttributeValue:NSAccessibilityWindowAttribute];
+ } else if ([attribute isEqualToString:NSAccessibilityTopLevelUIElementAttribute]) {
+ // We're in the same top level element as our parent.
+ return [parent accessibilityAttributeValue:NSAccessibilityTopLevelUIElementAttribute];
+ } else if ([attribute isEqualToString:NSAccessibilityPositionAttribute]) {
+ QPoint qtPosition = acast(accessibleInterface)->rect().topLeft();
+ QSize qtSize = acast(accessibleInterface)->rect().size();
+ return [NSValue valueWithPoint: NSMakePoint(qtPosition.x(), qt_mac_flipYCoordinate(qtPosition.y() + qtSize.height()))];
+ } else if ([attribute isEqualToString:NSAccessibilitySizeAttribute]) {
+ QSize qtSize = acast(accessibleInterface)->rect().size();
+ return [NSValue valueWithSize: NSMakeSize(qtSize.width(), qtSize.height())];
+ } else if ([attribute isEqualToString:NSAccessibilityDescriptionAttribute]) {
+ return qt_mac_QStringToNSString(acast(accessibleInterface)->text(QAccessible::Name));
+ }
+
+ return nil;
+}
+
+- (BOOL)accessibilityIsAttributeSettable:(NSString *)attribute {
+ if ([attribute isEqualToString:NSAccessibilityFocusedAttribute]) {
+ return NO; // YES to handle keyboard input
+ } else {
+ return NO;
+ }
+}
+
+- (void)accessibilitySetValue:(id)value forAttribute:(NSString *)attribute {
+ Q_UNUSED(value);
+ if ([attribute isEqualToString:NSAccessibilityFocusedAttribute]) {
+
+ }
+}
+
+// actions
+
+- (NSArray *)accessibilityActionNames {
+ return [NSArray arrayWithObject:NSAccessibilityPressAction];
+}
+
+- (NSString *)accessibilityActionDescription:(NSString *)action {
+ return NSAccessibilityActionDescription(action);
+}
+
+- (void)accessibilityPerformAction:(NSString *)action {
+ Q_UNUSED(action);
+ if (acast(accessibleInterface)->actionInterface())
+ acast(accessibleInterface)->actionInterface()->doAction(0);
+}
+
+// misc
+
+- (BOOL)accessibilityIsIgnored {
+ return NO;
+}
+
+- (id)accessibilityHitTest:(NSPoint)point {
+ Q_UNUSED(point);
+ return NSAccessibilityUnignoredAncestor(self);
+}
+
+- (id)accessibilityFocusedUIElement {
+ return NSAccessibilityUnignoredAncestor(self);
+}
+
+@end
diff --git a/src/plugins/platforms/cocoa/qnsview.h b/src/plugins/platforms/cocoa/qnsview.h
index 0b96928d5b..eddc1aa7e9 100644
--- a/src/plugins/platforms/cocoa/qnsview.h
+++ b/src/plugins/platforms/cocoa/qnsview.h
@@ -45,11 +45,13 @@
#include <Cocoa/Cocoa.h>
#include <QtGui/QImage>
+#include <QtGui/QAccessible>
@interface QNSView : NSView {
CGImageRef m_cgImage;
QWindow *m_window;
Qt::MouseButtons m_buttons;
+ QAccessibleInterface *m_accessibleRoot;
}
- (id)init;
diff --git a/src/plugins/platforms/cocoa/qnsview.mm b/src/plugins/platforms/cocoa/qnsview.mm
index 67bc61c63b..664b87607a 100644
--- a/src/plugins/platforms/cocoa/qnsview.mm
+++ b/src/plugins/platforms/cocoa/qnsview.mm
@@ -48,6 +48,10 @@
#include <QtGui/QWindowSystemInterface>
#include <QtCore/QDebug>
+#ifdef QT_COCOA_ENABLE_ACCESSIBILITY_INSPECTOR
+#include <accessibilityinspector.h>
+#endif
+
@interface NSEvent (Qt_Compile_Leopard_DeviceDelta)
- (CGFloat)deviceDeltaX;
- (CGFloat)deviceDeltaY;
@@ -58,7 +62,7 @@
- (id) init
{
- self = [super init];
+ self = [super initWithFrame : NSMakeRect(0,0, 300,300)];
if (self) {
m_cgImage = 0;
m_window = 0;
@@ -67,11 +71,31 @@
return self;
}
-- (id)initWithQWindow:(QWindow *)widget {
+- (id)initWithQWindow:(QWindow *)window {
self = [self init];
- if (self) {
- m_window = widget;
+ if (!self)
+ return 0;
+
+ m_window = window;
+ m_accessibleRoot = 0;
+
+#ifdef QT_COCOA_ENABLE_ACCESSIBILITY_INSPECTOR
+ // prevent rift in space-time continuum, disable
+ // accessibility for the accessibility inspector's windows.
+ static bool skipAccessibilityForInspectorWindows = false;
+ if (!skipAccessibilityForInspectorWindows) {
+
+ m_accessibleRoot = window->accessibleRoot();
+
+ AccessibilityInspector *inspector = new AccessibilityInspector(window);
+ skipAccessibilityForInspectorWindows = true;
+ inspector->inspectWindow(window);
+ skipAccessibilityForInspectorWindows = false;
}
+#else
+ m_accessibleRoot = window->accessibleRoot();
+#endif
+
return self;
}
diff --git a/src/plugins/platforms/cocoa/qnsviewaccessibility.mm b/src/plugins/platforms/cocoa/qnsviewaccessibility.mm
new file mode 100644
index 0000000000..327bace123
--- /dev/null
+++ b/src/plugins/platforms/cocoa/qnsviewaccessibility.mm
@@ -0,0 +1,117 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** 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.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <Carbon/Carbon.h>
+
+#include "qnsview.h"
+#include "qcocoahelpers.h"
+#include "qcocoaaccessibility.h"
+#include "qcocoaaccessibilityelement.h"
+
+#include "QAccessibleActionInterface"
+#include <QtCore/QDebug>
+
+#import <AppKit/NSAccessibility.h>
+
+@implementation QNSView (QNSViewAccessibility)
+
+- (BOOL)accessibilityIsIgnored {
+ return NO;
+}
+
+- (id)accessibilityAttributeValue:(NSString *)attribute {
+ if ([attribute isEqualToString:NSAccessibilityRoleAttribute]) {
+ if (m_accessibleRoot)
+ return macRole(m_accessibleRoot->role());
+ return NSAccessibilityUnknownRole;
+ } else if ([attribute isEqualToString:NSAccessibilityRoleDescriptionAttribute]) {
+ return NSAccessibilityRoleDescriptionForUIElement(self);
+ } else if ([attribute isEqualToString:NSAccessibilityChildrenAttribute]) {
+ if (!m_accessibleRoot)
+ return [super accessibilityAttributeValue:attribute];
+
+ // Create QCocoaAccessibleElements for each child if the
+ // root accessible interface.
+ int numKids = m_accessibleRoot->childCount();
+ NSMutableArray *kids = [NSMutableArray arrayWithCapacity:numKids];
+ for (int i = 0; i < numKids; ++i) {
+ [kids addObject:[QCocoaAccessibleElement elementWithIndex:i parent:self accessibleInterface:(void*)m_accessibleRoot->child(i)]];
+ }
+
+ return NSAccessibilityUnignoredChildren(kids);
+ } else {
+ return [super accessibilityAttributeValue:attribute];
+ }
+}
+
+- (id)accessibilityHitTest:(NSPoint)point {
+ NSPoint windowPoint = [[self window] convertScreenToBase:point];
+ NSPoint localPoint = [self convertPoint:windowPoint fromView:nil];
+
+ int index = -1;
+ if (m_accessibleRoot) {
+ index = m_accessibleRoot->childAt(point.x, qt_mac_flipYCoordinate(point.y));
+
+ // qDebug() << "root rect" << m_accessibleRoot->rect();
+ // qDebug() << "hit screen" << point.x << qt_mac_flipYCoordinate(point.y) << index;
+ // if (index > 0) {
+ // qDebug() << "child name" << m_accessibleRoot->child(index - 1)->text(QAccessible::Name);
+ // qDebug() << "child rect" << m_accessibleRoot->child(index - 1)->rect();
+ // }
+ }
+
+ // hit outside
+ if (index == -1) {
+ return [super accessibilityHitTest:point];
+ }
+
+ // hit the NSView / top-level window
+ if (index == 0) {
+ QCocoaAccessibleElement *accessibleElement = [QCocoaAccessibleElement elementWithIndex:index parent:self accessibleInterface:(void*)m_accessibleRoot];
+ return [accessibleElement accessibilityHitTest:point];
+ }
+
+ // hit a child, forward to child accessible interface.
+ QCocoaAccessibleElement *accessibleElement = [QCocoaAccessibleElement elementWithIndex:index - 1 parent:self accessibleInterface:(void*)m_accessibleRoot->child(index -1)];
+ return [accessibleElement accessibilityHitTest:point];
+}
+
+@end