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.mm137
1 files changed, 95 insertions, 42 deletions
diff --git a/src/plugins/platforms/cocoa/qcocoaaccessibilityelement.mm b/src/plugins/platforms/cocoa/qcocoaaccessibilityelement.mm
index dd76852b62..b91831bad8 100644
--- a/src/plugins/platforms/cocoa/qcocoaaccessibilityelement.mm
+++ b/src/plugins/platforms/cocoa/qcocoaaccessibilityelement.mm
@@ -1,40 +1,32 @@
/****************************************************************************
**
-** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
-** Contact: http://www.qt-project.org/legal
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
**
** This file is part of the plugins of the Qt Toolkit.
**
-** $QT_BEGIN_LICENSE:LGPL$
+** $QT_BEGIN_LICENSE:LGPL21$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and Digia. For licensing terms and
-** conditions see http://qt.digia.com/licensing. For further information
-** use the contact form at http://qt.digia.com/contact-us.
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
**
** 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.
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
-** In addition, as a special exception, Digia gives you certain additional
-** rights. These rights are described in the Digia Qt LGPL Exception
+** As a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company 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.
-**
-**
** $QT_END_LICENSE$
**
****************************************************************************/
@@ -48,6 +40,47 @@
#import <AppKit/NSAccessibility.h>
+
+static void convertLineOffset(QAccessibleTextInterface *text, int &line, int &offset, NSUInteger *start = 0, NSUInteger *end = 0)
+{
+ Q_ASSERT(line == -1 || offset == -1);
+ Q_ASSERT(line != -1 || offset != -1);
+ Q_ASSERT(offset <= text->characterCount());
+
+ int curLine = -1;
+ int curStart = 0, curEnd = 0;
+
+ do {
+ curStart = curEnd;
+ text->textAtOffset(curStart, QAccessible::LineBoundary, &curStart, &curEnd);
+ ++curLine;
+ {
+ // check for a case where a single word longer than the text edit's width and gets wrapped
+ // in the middle of the word; in this case curEnd will be an offset belonging to the next line
+ // and therefore nextEnd will not be equal to curEnd
+ int nextStart;
+ int nextEnd;
+ text->textAtOffset(curEnd, QAccessible::LineBoundary, &nextStart, &nextEnd);
+ if (nextEnd == curEnd)
+ ++curEnd;
+ }
+ } while ((line == -1 || curLine < line) && (offset == -1 || (curEnd <= offset)) && curEnd <= text->characterCount());
+
+ curEnd = qMin(curEnd, text->characterCount());
+
+ if (line == -1)
+ line = curLine;
+ if (offset == -1)
+ offset = curStart;
+
+ Q_ASSERT(curStart >= 0);
+ Q_ASSERT(curEnd >= 0);
+ if (start)
+ *start = curStart;
+ if (end)
+ *end = curEnd;
+}
+
@implementation QMacAccessibilityElement
- (id)initWithId:(QAccessible::Id)anId
@@ -225,7 +258,7 @@
} else if ([attribute isEqualToString:NSAccessibilitySubroleAttribute]) {
return QCocoaAccessible::macSubrole(iface);
} else if ([attribute isEqualToString:NSAccessibilityRoleDescriptionAttribute]) {
- return NSAccessibilityRoleDescription(role, nil);
+ return NSAccessibilityRoleDescription(role, [self accessibilityAttributeValue:NSAccessibilitySubroleAttribute]);
} else if ([attribute isEqualToString:NSAccessibilityChildrenAttribute]) {
return QCocoaAccessible::unignoredChildren(iface);
} else if ([attribute isEqualToString:NSAccessibilityFocusedAttribute]) {
@@ -292,8 +325,10 @@
} else if ([attribute isEqualToString:NSAccessibilityInsertionPointLineNumberAttribute]) {
if (QAccessibleTextInterface *text = iface->textInterface()) {
- QString textBeforeCursor = text->text(0, text->cursorPosition());
- return [NSNumber numberWithInt: textBeforeCursor.count(QLatin1Char('\n'))];
+ int line = -1;
+ int position = text->cursorPosition();
+ convertLineOffset(text, line, position);
+ return [NSNumber numberWithInt: line];
}
return nil;
} else if ([attribute isEqualToString:NSAccessibilityMinValueAttribute]) {
@@ -322,7 +357,7 @@
// NSAccessibilityRangeForIndexParameterizedAttribute,
NSAccessibilityBoundsForRangeParameterizedAttribute,
// NSAccessibilityRTFForRangeParameterizedAttribute,
-// NSAccessibilityStyleRangeForIndexParameterizedAttribute,
+ NSAccessibilityStyleRangeForIndexParameterizedAttribute,
NSAccessibilityAttributedStringForRangeParameterizedAttribute,
nil
];
@@ -348,34 +383,52 @@
}
if ([attribute isEqualToString: NSAccessibilityLineForIndexParameterizedAttribute]) {
int index = [parameter intValue];
- NSNumber *ln = [QMacAccessibilityElement lineNumberForIndex: index forText: iface->text(QAccessible::Value)];
- return ln;
+ if (index < 0 || index > iface->textInterface()->characterCount())
+ return nil;
+ int line = -1;
+ convertLineOffset(iface->textInterface(), line, index);
+ return [NSNumber numberWithInt:line];
}
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);
- if (endOffset == -1)
- endOffset = text.length();
- return [NSValue valueWithRange:NSMakeRange(quint32(startOffset), quint32(endOffset - startOffset))];
+ int line = [parameter intValue];
+ if (line < 0)
+ return nil;
+ int lineOffset = -1;
+ NSUInteger startOffset = 0;
+ NSUInteger endOffset = 0;
+ convertLineOffset(iface->textInterface(), line, lineOffset, &startOffset, &endOffset);
+ return [NSValue valueWithRange:NSMakeRange(startOffset, 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
+ QRect rect;
+ if (range.length > 0) {
+ NSUInteger position = range.location + range.length - 1;
+ if (position > range.location && iface->textInterface()->text(position, position + 1) == QStringLiteral("\n"))
+ --position;
+ QRect lastRect = iface->textInterface()->characterRect(position);
+ rect = firstRect.united(lastRect);
+ } else {
+ rect = firstRect;
+ rect.setWidth(1);
+ }
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()];
+ } else if ([attribute isEqualToString: NSAccessibilityRangeForPositionParameterizedAttribute]) {
+ NSPoint nsPoint = [parameter pointValue];
+ QPoint point(static_cast<int>(nsPoint.x), static_cast<int>(qt_mac_flipYCoordinate(nsPoint.y)));
+ int offset = iface->textInterface()->offsetAtPoint(point);
+ return [NSValue valueWithRange:NSMakeRange(static_cast<NSUInteger>(offset), 1)];
+ } else if ([attribute isEqualToString: NSAccessibilityStyleRangeForIndexParameterizedAttribute]) {
+ int start = 0;
+ int end = 0;
+ iface->textInterface()->attributes([parameter intValue], &start, &end);
+ return [NSValue valueWithRange:NSMakeRange(static_cast<NSUInteger>(start), static_cast<NSUInteger>(end - start))];
}
return nil;
}