summaryrefslogtreecommitdiffstats
path: root/src/plugins/platforms/cocoa/qcocoaaccessibilityelement.mm
diff options
context:
space:
mode:
Diffstat (limited to 'src/plugins/platforms/cocoa/qcocoaaccessibilityelement.mm')
-rw-r--r--src/plugins/platforms/cocoa/qcocoaaccessibilityelement.mm157
1 files changed, 152 insertions, 5 deletions
diff --git a/src/plugins/platforms/cocoa/qcocoaaccessibilityelement.mm b/src/plugins/platforms/cocoa/qcocoaaccessibilityelement.mm
index 66c7727f15..bc98d002f0 100644
--- a/src/plugins/platforms/cocoa/qcocoaaccessibilityelement.mm
+++ b/src/plugins/platforms/cocoa/qcocoaaccessibilityelement.mm
@@ -91,6 +91,13 @@
// attributes
++ (id) lineNumberForIndex: (int)index forText:(const QString &)text
+{
+ QStringRef textBefore = QStringRef(&text, 0, index);
+ int newlines = textBefore.count(QLatin1Char('\n'));
+ return [NSNumber numberWithInt: newlines];
+}
+
- (NSArray *)accessibilityAttributeNames {
static NSArray *defaultAttributes = nil;
@@ -121,6 +128,19 @@
[attributes addObject : NSAccessibilityValueAttribute];
}
+ if (iface->textInterface()) {
+ [attributes addObjectsFromArray: [[NSArray alloc] initWithObjects:
+ NSAccessibilityNumberOfCharactersAttribute,
+ NSAccessibilitySelectedTextAttribute,
+ NSAccessibilitySelectedTextRangeAttribute,
+ NSAccessibilityVisibleCharacterRangeAttribute,
+ NSAccessibilityInsertionPointLineNumberAttribute,
+ nil
+ ]];
+
+// TODO: multi-selection: NSAccessibilitySelectedTextRangesAttribute,
+ }
+
return [attributes autorelease];
}
@@ -167,23 +187,150 @@
return nil;
return QCocoaAccessible::getValueAttribute(iface);
+
+ } else if ([attribute isEqualToString:NSAccessibilityNumberOfCharactersAttribute]) {
+ if (QAccessibleTextInterface *text = iface->textInterface())
+ return [NSNumber numberWithInt: text->characterCount()];
+ return nil;
+ } else if ([attribute isEqualToString:NSAccessibilitySelectedTextAttribute]) {
+ if (QAccessibleTextInterface *text = iface->textInterface()) {
+ int start = 0;
+ int end = 0;
+ text->selection(0, &start, &end);
+ return text->text(start, end).toNSString();
+ }
+ return nil;
+ } else if ([attribute isEqualToString:NSAccessibilitySelectedTextRangeAttribute]) {
+ if (QAccessibleTextInterface *text = iface->textInterface()) {
+ int start = 0;
+ int end = 0;
+ if (text->selectionCount() > 0) {
+ text->selection(0, &start, &end);
+ } else {
+ start = text->cursorPosition();
+ end = start;
+ }
+ return [NSValue valueWithRange:NSMakeRange(quint32(start), quint32(end - start))];
+ }
+ return [NSValue valueWithRange: NSMakeRange(0, 0)];
+ } else if ([attribute isEqualToString:NSAccessibilityVisibleCharacterRangeAttribute]) {
+ // FIXME This is not correct and may impact performance for big texts
+ return [NSValue valueWithRange: NSMakeRange(0, iface->textInterface()->characterCount())];
+
+ } else if ([attribute isEqualToString:NSAccessibilityInsertionPointLineNumberAttribute]) {
+ if (QAccessibleTextInterface *text = iface->textInterface()) {
+ QString textBeforeCursor = text->text(0, text->cursorPosition());
+ return [NSNumber numberWithInt: textBeforeCursor.count(QLatin1Char('\n'))];
+ }
+ return nil;
+ }
+
+ return nil;
+}
+
+- (NSArray *)accessibilityParameterizedAttributeNames {
+
+ QAccessibleInterface *iface = QAccessible::accessibleInterface(axid);
+ if (!iface) {
+ qWarning() << "Called attribute on invalid object: " << axid;
+ return nil;
+ }
+
+ if (iface->textInterface()) {
+ return [[NSArray alloc] initWithObjects:
+ NSAccessibilityStringForRangeParameterizedAttribute,
+ NSAccessibilityLineForIndexParameterizedAttribute,
+ NSAccessibilityRangeForLineParameterizedAttribute,
+ NSAccessibilityRangeForPositionParameterizedAttribute,
+// NSAccessibilityRangeForIndexParameterizedAttribute,
+ NSAccessibilityBoundsForRangeParameterizedAttribute,
+// NSAccessibilityRTFForRangeParameterizedAttribute,
+// NSAccessibilityStyleRangeForIndexParameterizedAttribute,
+ NSAccessibilityAttributedStringForRangeParameterizedAttribute,
+ nil
+ ];
+ }
+
+ return nil;
+}
+
+- (id)accessibilityAttributeValue:(NSString *)attribute forParameter:(id)parameter {
+ QAccessibleInterface *iface = QAccessible::accessibleInterface(axid);
+ if (!iface) {
+ qWarning() << "Called attribute on invalid object: " << axid;
+ return nil;
}
+ if (!iface->textInterface())
+ return nil;
+
+ if ([attribute isEqualToString: NSAccessibilityStringForRangeParameterizedAttribute]) {
+ NSRange range = [parameter rangeValue];
+ QString text = iface->textInterface()->text(range.location, range.location + range.length);
+ return text.toNSString();
+ }
+ if ([attribute isEqualToString: NSAccessibilityLineForIndexParameterizedAttribute]) {
+ int index = [parameter intValue];
+ NSNumber *ln = [QCocoaAccessibleElement lineNumberForIndex: index forText: iface->text(QAccessible::Value)];
+ return ln;
+ }
+ if ([attribute isEqualToString: NSAccessibilityRangeForLineParameterizedAttribute]) {
+ int lineNumber = [parameter intValue];
+ QString text = iface->text(QAccessible::Value);
+ int startOffset = 0;
+ // skip newlines until we have the one we look for
+ for (int i = 0; i < lineNumber; ++i)
+ startOffset = text.indexOf(QLatin1Char('\n'), startOffset) + 1;
+ if (startOffset < 0) // invalid line number, return the first line
+ startOffset = 0;
+ int endOffset = text.indexOf(QLatin1Char('\n'), startOffset + 1);
+ if (endOffset == -1)
+ endOffset = text.length();
+ return [NSValue valueWithRange:NSMakeRange(quint32(startOffset), quint32(endOffset - startOffset))];
+ }
+ if ([attribute isEqualToString: NSAccessibilityBoundsForRangeParameterizedAttribute]) {
+ NSRange range = [parameter rangeValue];
+ QRect firstRect = iface->textInterface()->characterRect(range.location);
+ QRect lastRect = iface->textInterface()->characterRect(range.location + range.length);
+ QRect rect = firstRect.united(lastRect); // This is off quite often, but at least a rough approximation
+ return [NSValue valueWithRect: NSMakeRect((CGFloat) rect.x(),(CGFloat) qt_mac_flipYCoordinate(rect.y() + rect.height()), rect.width(), rect.height())];
+ }
+ if ([attribute isEqualToString: NSAccessibilityAttributedStringForRangeParameterizedAttribute]) {
+ NSRange range = [parameter rangeValue];
+ QString text = iface->textInterface()->text(range.location, range.location + range.length);
+ return [[NSAttributedString alloc] initWithString: text.toNSString()];
+ }
return nil;
}
- (BOOL)accessibilityIsAttributeSettable:(NSString *)attribute {
+ QAccessibleInterface *iface = QAccessible::accessibleInterface(axid);
+ if (!iface)
+ return nil;
+
if ([attribute isEqualToString:NSAccessibilityFocusedAttribute]) {
- return NO; // YES to handle keyboard input
- } else {
- return NO;
+ return iface->state().focusable ? YES : NO;
+ } else if ([attribute isEqualToString:NSAccessibilitySelectedTextRangeAttribute]) {
+ return iface->textInterface() ? YES : NO;
}
+ return NO;
}
- (void)accessibilitySetValue:(id)value forAttribute:(NSString *)attribute {
- Q_UNUSED(value);
+ QAccessibleInterface *iface = QAccessible::accessibleInterface(axid);
+ if (!iface)
+ return;
if ([attribute isEqualToString:NSAccessibilityFocusedAttribute]) {
-
+ if (QAccessibleActionInterface *action = iface->actionInterface())
+ action->doAction(QAccessibleActionInterface::setFocusAction());
+ } else if ([attribute isEqualToString:NSAccessibilitySelectedTextRangeAttribute]) {
+ if (QAccessibleTextInterface *text = iface->textInterface()) {
+ NSRange range = [value rangeValue];
+ if (range.length > 0)
+ text->setSelection(0, range.location, range.location + range.length);
+ else
+ text->setCursorPosition(range.location);
+ }
}
}