summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/plugins/platforms/cocoa/qcocoaaccessibilityelement.mm18
-rw-r--r--src/plugins/platforms/cocoa/qnsviewaccessibility.mm53
-rw-r--r--tests/auto/other/qaccessibilitymac/tst_qaccessibilitymac.cpp20
-rw-r--r--tests/auto/other/qaccessibilitymac/tst_qaccessibilitymac_helpers.h3
-rw-r--r--tests/auto/other/qaccessibilitymac/tst_qaccessibilitymac_helpers.mm83
5 files changed, 121 insertions, 56 deletions
diff --git a/src/plugins/platforms/cocoa/qcocoaaccessibilityelement.mm b/src/plugins/platforms/cocoa/qcocoaaccessibilityelement.mm
index bc98d002f0..0b674b8d2f 100644
--- a/src/plugins/platforms/cocoa/qcocoaaccessibilityelement.mm
+++ b/src/plugins/platforms/cocoa/qcocoaaccessibilityelement.mm
@@ -417,7 +417,23 @@
}
- (id)accessibilityFocusedUIElement {
- return NSAccessibilityUnignoredAncestor(self);
+ QAccessibleInterface *iface = QAccessible::accessibleInterface(axid);
+
+ if (!iface || !iface->isValid()) {
+ qWarning() << "FocusedUIElement for INVALID";
+ return nil;
+ }
+ QAccessibleInterface *childInterface = iface->focusChild();
+ if (childInterface) {
+ QAccessible::Id childAxid = QAccessible::uniqueId(childInterface);
+ // FIXME: parent could be wrong
+ QCocoaAccessibleElement *accessibleElement = [QCocoaAccessibleElement createElementWithId:childAxid parent:self];
+ [accessibleElement autorelease];
+ return accessibleElement;
+ }
+
+ // no focus found
+ return nil;
}
@end
diff --git a/src/plugins/platforms/cocoa/qnsviewaccessibility.mm b/src/plugins/platforms/cocoa/qnsviewaccessibility.mm
index a438950a55..31e3e343b9 100644
--- a/src/plugins/platforms/cocoa/qnsviewaccessibility.mm
+++ b/src/plugins/platforms/cocoa/qnsviewaccessibility.mm
@@ -54,6 +54,15 @@
@implementation QNSView (QNSViewAccessibility)
+- (id)childAccessibleElement {
+ if (!m_window->accessibleRoot())
+ return nil;
+
+ QAccessible::Id childId = QAccessible::uniqueId(m_window->accessibleRoot());
+ QCocoaAccessibleElement *child = [QCocoaAccessibleElement createElementWithId: childId parent: self];
+ return [child autorelease];
+}
+
// The QNSView is a container that the user does not interact directly with:
// Remove it from the user-visible accessibility tree.
- (BOOL)accessibilityIsIgnored {
@@ -61,58 +70,22 @@
}
- (id)accessibilityAttributeValue:(NSString *)attribute {
-
// activate accessibility updates
QCocoaIntegration::instance()->accessibility()->setActive(true);
- if ([attribute isEqualToString:NSAccessibilityRoleAttribute]) {
- if (m_window->accessibleRoot())
- return QCocoaAccessible::macRole(m_window->accessibleRoot());
- return NSAccessibilityUnknownRole;
- } else if ([attribute isEqualToString:NSAccessibilityRoleDescriptionAttribute]) {
- return NSAccessibilityRoleDescriptionForUIElement(self);
- } else if ([attribute isEqualToString:NSAccessibilityChildrenAttribute]) {
- if (!m_window->accessibleRoot())
- return [super accessibilityAttributeValue:attribute];
- return QCocoaAccessible::unignoredChildren(self, m_window->accessibleRoot());
+ if ([attribute isEqualToString:NSAccessibilityChildrenAttribute]) {
+ return NSAccessibilityUnignoredChildrenForOnlyChild([self childAccessibleElement]);
} else {
return [super accessibilityAttributeValue:attribute];
}
}
- (id)accessibilityHitTest:(NSPoint)point {
- if (!m_window->accessibleRoot())
- return [super accessibilityHitTest:point];
-
- QAccessibleInterface *childInterface = m_window->accessibleRoot()->childAt(point.x, qt_mac_flipYCoordinate(point.y));
- // No child found, meaning we hit the NSView
- if (!childInterface) {
- return [super accessibilityHitTest:point];
- }
-
- // Hit a child, forward to child accessible interface.
- QAccessible::Id childAxid = QAccessible::uniqueId(childInterface);
- // FIXME: parent could be wrong
- QCocoaAccessibleElement *accessibleElement = [QCocoaAccessibleElement createElementWithId:childAxid parent:self ];
- [accessibleElement autorelease];
- return [accessibleElement accessibilityHitTest:point];
+ return [[self childAccessibleElement] accessibilityHitTest: point];
}
- (id)accessibilityFocusedUIElement {
- if (!m_window->accessibleRoot())
- return [super accessibilityFocusedUIElement];
-
- QAccessibleInterface *childInterface = m_window->accessibleRoot()->focusChild();
- if (childInterface) {
- QAccessible::Id childAxid = QAccessible::uniqueId(childInterface);
- // FIXME: parent could be wrong
- QCocoaAccessibleElement *accessibleElement = [QCocoaAccessibleElement createElementWithId:childAxid parent:self];
- [accessibleElement autorelease];
- return accessibleElement;
- }
-
- // should not happen
- return nil;
+ return [[self childAccessibleElement] accessibilityFocusedUIElement];
}
@end
diff --git a/tests/auto/other/qaccessibilitymac/tst_qaccessibilitymac.cpp b/tests/auto/other/qaccessibilitymac/tst_qaccessibilitymac.cpp
index 25dd0d39dd..25b47ee836 100644
--- a/tests/auto/other/qaccessibilitymac/tst_qaccessibilitymac.cpp
+++ b/tests/auto/other/qaccessibilitymac/tst_qaccessibilitymac.cpp
@@ -79,6 +79,7 @@ private slots:
void init();
void cleanup();
+ void singleWidgetTest();
void lineEditTest();
void hierarchyTest();
private:
@@ -101,6 +102,16 @@ void tst_QAccessibilityMac::cleanup()
delete m_window;
}
+void tst_QAccessibilityMac::singleWidgetTest()
+{
+ if (!macNativeAccessibilityEnabled())
+ return;
+
+ delete m_window;
+ m_window = 0;
+
+ QVERIFY(singleWidget());
+}
void tst_QAccessibilityMac::lineEditTest()
{
@@ -122,14 +133,19 @@ void tst_QAccessibilityMac::hierarchyTest()
QWidget *w = new QWidget(m_window);
m_window->addWidget(w);
- QPushButton *b = new QPushButton(w);
+
w->setLayout(new QVBoxLayout());
+ QPushButton *b = new QPushButton(w);
w->layout()->addWidget(b);
b->setText("I am a button");
+ QPushButton *b2 = new QPushButton(w);
+ w->layout()->addWidget(b2);
+ b2->setText("Button 2");
+
QVERIFY(QTest::qWaitForWindowExposed(m_window));
QCoreApplication::processEvents();
- QVERIFY(testHierarchy());
+ QVERIFY(testHierarchy(w));
}
QTEST_MAIN(tst_QAccessibilityMac)
diff --git a/tests/auto/other/qaccessibilitymac/tst_qaccessibilitymac_helpers.h b/tests/auto/other/qaccessibilitymac/tst_qaccessibilitymac_helpers.h
index ec5beab125..635b6383ab 100644
--- a/tests/auto/other/qaccessibilitymac/tst_qaccessibilitymac_helpers.h
+++ b/tests/auto/other/qaccessibilitymac/tst_qaccessibilitymac_helpers.h
@@ -48,4 +48,5 @@
bool macNativeAccessibilityEnabled();
bool trusted();
bool testLineEdit();
-bool testHierarchy();
+bool testHierarchy(QWidget *w);
+bool singleWidget();
diff --git a/tests/auto/other/qaccessibilitymac/tst_qaccessibilitymac_helpers.mm b/tests/auto/other/qaccessibilitymac/tst_qaccessibilitymac_helpers.mm
index 8620b7dd2f..bc89ac858b 100644
--- a/tests/auto/other/qaccessibilitymac/tst_qaccessibilitymac_helpers.mm
+++ b/tests/auto/other/qaccessibilitymac/tst_qaccessibilitymac_helpers.mm
@@ -43,8 +43,10 @@
#define QT_NO_KEYWORDS
#include "tst_qaccessibilitymac_helpers.h"
-#include <QApplication>
-#include <QDebug>
+#include <QtWidgets/qapplication.h>
+#include <QtWidgets/qlineedit.h>
+#include <QtWidgets/qpushbutton.h>
+#include <QtTest>
#include <unistd.h>
#import <Cocoa/Cocoa.h>
@@ -148,9 +150,41 @@ bool trusted()
return p;
}
++ (TestAXObject *) getApplicationAXObject
+{
+ pid_t pid = getpid();
+ AXUIElementRef appRef = AXUIElementCreateApplication(pid);
+ TestAXObject *appObject = [[TestAXObject alloc] initWithAXUIElementRef: appRef];
+ return appObject;
+}
+
@end
+bool singleWidget()
+{
+ QLineEdit le;
+ le.setText("button");
+ le.show();
+ EXPECT(QTest::qWaitForWindowExposed(&le));
+ QCoreApplication::processEvents();
+
+ TestAXObject *appObject = [TestAXObject getApplicationAXObject];
+ EXPECT(appObject);
+
+ NSArray *windows = [appObject windowList];
+ EXPECT([windows count] == 1);
+
+ AXUIElementRef windowRef = (AXUIElementRef) [windows objectAtIndex: 0];
+ EXPECT(windowRef != nil);
+ TestAXObject *window = [[TestAXObject alloc] initWithAXUIElementRef: windowRef];
+
+ AXUIElementRef lineEdit = [window findDirectChildByRole: kAXTextFieldRole];
+ EXPECT(lineEdit != nil);
+
+ return true;
+}
+
bool testLineEdit()
{
// not sure if this is needed. on my machine the calls succeed.
@@ -159,10 +193,8 @@ bool testLineEdit()
// AXError e = AXMakeProcessTrusted((CFStringRef) path);
// NSLog(@"error: %i", e);
- pid_t pid = getpid();
- AXUIElementRef app = AXUIElementCreateApplication(pid);
- EXPECT(app != nil);
- TestAXObject *appObject = [[TestAXObject alloc] initWithAXUIElementRef: app];
+ TestAXObject *appObject = [TestAXObject getApplicationAXObject];
+ EXPECT(appObject);
NSArray *windowList = [appObject windowList];
// one window
@@ -184,12 +216,10 @@ bool testLineEdit()
return true;
}
-bool testHierarchy()
+bool testHierarchy(QWidget *w)
{
- pid_t pid = getpid();
- AXUIElementRef app = AXUIElementCreateApplication(pid);
- EXPECT(app != nil);
- TestAXObject *appObject = [[TestAXObject alloc] initWithAXUIElementRef: app];
+ TestAXObject *appObject = [TestAXObject getApplicationAXObject];
+ EXPECT(appObject);
NSArray *windowList = [appObject windowList];
// one window
@@ -207,7 +237,36 @@ bool testHierarchy()
TestAXObject *parentObject = [[TestAXObject alloc] initWithAXUIElementRef: [buttonObject parent]];
// check that the parent is a window
- EXPECT([[parentObject role] isEqualToString: (NSString *)kAXWindowRole]);
+ EXPECT([[parentObject role] isEqualToString: NSAccessibilityWindowRole]);
+
+ // test the focus
+ // child 0 is the layout, then button1 and 2
+ QPushButton *button1 = qobject_cast<QPushButton*>(w->children().at(1));
+ EXPECT(button1);
+ QPushButton *button2 = qobject_cast<QPushButton*>(w->children().at(2));
+ EXPECT(button2);
+ button2->setFocus();
+
+ AXUIElementRef systemWideElement = AXUIElementCreateSystemWide();
+ AXUIElementRef focussedElement = NULL;
+ AXError error = AXUIElementCopyAttributeValue(systemWideElement,
+ (CFStringRef)NSAccessibilityFocusedUIElementAttribute, (CFTypeRef*)&focussedElement);
+ EXPECT(!error);
+ EXPECT(focussedElement);
+ TestAXObject *focusButton2 = [[TestAXObject alloc] initWithAXUIElementRef: focussedElement];
+
+ EXPECT([[focusButton2 role] isEqualToString: NSAccessibilityButtonRole]);
+ EXPECT([[focusButton2 description] isEqualToString: @"Button 2"]);
+
+
+ button1->setFocus();
+ error = AXUIElementCopyAttributeValue(systemWideElement,
+ (CFStringRef)NSAccessibilityFocusedUIElementAttribute, (CFTypeRef*)&focussedElement);
+ EXPECT(!error);
+ EXPECT(focussedElement);
+ TestAXObject *focusButton1 = [[TestAXObject alloc] initWithAXUIElementRef: focussedElement];
+ EXPECT([[focusButton1 role] isEqualToString: NSAccessibilityButtonRole]);
+ EXPECT([[focusButton1 description] isEqualToString: @"I am a button"]);
return true;
}