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.mm508
1 files changed, 326 insertions, 182 deletions
diff --git a/src/plugins/platforms/cocoa/qcocoaaccessibilityelement.mm b/src/plugins/platforms/cocoa/qcocoaaccessibilityelement.mm
index 68e7947162..b319dd072e 100644
--- a/src/plugins/platforms/cocoa/qcocoaaccessibilityelement.mm
+++ b/src/plugins/platforms/cocoa/qcocoaaccessibilityelement.mm
@@ -9,12 +9,17 @@
#include "qcocoawindow.h"
#include "qcocoascreen.h"
+#include <QtCore/qlogging.h>
#include <QtGui/private/qaccessiblecache_p.h>
#include <QtGui/private/qaccessiblebridgeutils_p.h>
#include <QtGui/qaccessible.h>
QT_USE_NAMESPACE
+Q_LOGGING_CATEGORY(lcAccessibilityTable, "qt.accessibility.table")
+
+using namespace Qt::Literals::StringLiterals;
+
#if QT_CONFIG(accessibility)
/**
@@ -80,6 +85,8 @@ static void convertLineOffset(QAccessibleTextInterface *text, int *line, int *of
@implementation QMacAccessibilityElement {
QAccessible::Id axid;
+ int m_rowIndex;
+ int m_columnIndex;
// used by NSAccessibilityTable
NSMutableArray<QMacAccessibilityElement *> *rows; // corresponds to accessibilityRows
@@ -105,12 +112,65 @@ static void convertLineOffset(QAccessibleTextInterface *text, int *line, int *of
self = [super init];
if (self) {
axid = anId;
+ m_rowIndex = -1;
+ m_columnIndex = -1;
rows = nil;
columns = nil;
synthesizedRole = role;
- QAccessibleInterface *iface = QAccessible::accessibleInterface(axid);
- if (iface && iface->tableInterface() && !synthesizedRole)
- [self updateTableModel];
+ // table: if this is not created as an element managed by the table, then
+ // it's either the table itself, or an element created for an already existing
+ // cell interface (or an element that's not at all related to a table).
+ if (!synthesizedRole) {
+ if (QAccessibleInterface *iface = QAccessible::accessibleInterface(axid)) {
+ if (iface->tableInterface()) {
+ [self updateTableModel];
+ } else if (const auto *cell = iface->tableCellInterface()) {
+ // If we create an element for a table cell, initialize it with row/column
+ // and insert it into the corresponding row's columns array.
+ m_rowIndex = cell->rowIndex();
+ m_columnIndex = cell->columnIndex();
+ QAccessibleInterface *table = cell->table();
+ Q_ASSERT(table);
+ QAccessibleTableInterface *tableInterface = table->tableInterface();
+ if (tableInterface) {
+ auto *tableElement = [QMacAccessibilityElement elementWithInterface:table];
+ Q_ASSERT(tableElement);
+ if (!tableElement->rows
+ || int(tableElement->rows.count) <= m_rowIndex
+ || int(tableElement->rows.count) != tableInterface->rowCount()) {
+ qCWarning(lcAccessibilityTable)
+ << "Cell requested for row" << m_rowIndex << "is out of"
+ << "bounds for table with" << (tableElement->rows ?
+ tableElement->rows.count : tableInterface->rowCount())
+ << "rows! Resizing table model.";
+ [tableElement updateTableModel];
+ }
+
+ Q_ASSERT(tableElement->rows);
+ Q_ASSERT(int(tableElement->rows.count) > m_rowIndex);
+
+ auto *rowElement = tableElement->rows[m_rowIndex];
+ if (!rowElement->columns || int(rowElement->columns.count) != tableInterface->columnCount()) {
+ if (rowElement->columns) {
+ qCWarning(lcAccessibilityTable)
+ << "Table representation column count is out of sync:"
+ << rowElement->columns.count << "!=" << tableInterface->columnCount();
+ }
+ rowElement->columns = [rowElement populateTableRow:rowElement->columns
+ count:tableInterface->columnCount()];
+ }
+
+ qCDebug(lcAccessibilityTable) << "Creating cell representation for"
+ << m_rowIndex << m_columnIndex
+ << "in table with"
+ << tableElement->rows.count << "rows and"
+ << rowElement->columns.count << "columns";
+
+ rowElement->columns[m_columnIndex] = self;
+ }
+ }
+ }
+ }
}
return self;
@@ -126,16 +186,23 @@ static void convertLineOffset(QAccessibleTextInterface *text, int *line, int *of
QMacAccessibilityElement *element = cache->elementForId(anId);
if (!element) {
- QAccessibleInterface *iface = QAccessible::accessibleInterface(anId);
- Q_ASSERT(iface);
- if (!iface || !iface->isValid())
- return nil;
+ Q_ASSERT(QAccessible::accessibleInterface(anId));
element = [[self alloc] initWithId:anId];
cache->insertElement(anId, element);
}
return element;
}
++ (instancetype)elementWithInterface:(QAccessibleInterface *)iface
+{
+ Q_ASSERT(iface);
+ if (!iface)
+ return nil;
+
+ const QAccessible::Id anId = QAccessible::uniqueId(iface);
+ return [self elementWithId:anId];
+}
+
- (void)invalidate {
axid = 0;
rows = nil;
@@ -173,8 +240,11 @@ static void convertLineOffset(QAccessibleTextInterface *text, int *line, int *of
- (NSMutableArray *)populateTableArray:(NSMutableArray *)array role:(NSAccessibilityRole)role count:(int)count
{
- QAccessibleInterface *iface = QAccessible::accessibleInterface(axid);
- if (iface && iface->isValid()) {
+ if (QAccessibleInterface *iface = self.qtInterface) {
+ if (array && int(array.count) != count) {
+ [array release];
+ array = nil;
+ }
if (!array) {
array = [NSMutableArray<QMacAccessibilityElement *> arrayWithCapacity:count];
[array retain];
@@ -187,6 +257,10 @@ static void convertLineOffset(QAccessibleTextInterface *text, int *line, int *of
QMacAccessibilityElement *element =
[[QMacAccessibilityElement alloc] initWithId:axid role:role];
if (element) {
+ if (role == NSAccessibilityRowRole)
+ element->m_rowIndex = n;
+ else if (role == NSAccessibilityColumnRole)
+ element->m_columnIndex = n;
[array addObject:element];
[element release];
} else {
@@ -198,29 +272,99 @@ static void convertLineOffset(QAccessibleTextInterface *text, int *line, int *of
return nil;
}
+- (NSMutableArray *)populateTableRow:(NSMutableArray *)array count:(int)count
+{
+ Q_ASSERT(synthesizedRole == NSAccessibilityRowRole);
+ if (array && int(array.count) != count) {
+ [array release];
+ array = nil;
+ }
+
+ if (!array) {
+ array = [NSMutableArray<QMacAccessibilityElement *> arrayWithCapacity:count];
+ [array retain];
+ // When macOS asks for the children of a row, then we populate the row's column
+ // array with synthetic elements as place holders. This way, we don't have to
+ // create QAccessibleInterfaces for every cell before they are really needed.
+ // We don't add those synthetic elements into the cache, and we give them the
+ // same axid as the table. This way, we can get easily to the table, and from
+ // there to the QAccessibleInterface for the cell, when we have to eventually
+ // associate such an interface with the element (at which point it is no longer
+ // a placeholder).
+ for (int n = 0; n < count; ++n) {
+ // columns will have same axid as table (but not inserted in cache)
+ QMacAccessibilityElement *cell =
+ [[QMacAccessibilityElement alloc] initWithId:axid role:NSAccessibilityCellRole];
+ if (cell) {
+ cell->m_rowIndex = m_rowIndex;
+ cell->m_columnIndex = n;
+ [array addObject:cell];
+ }
+ }
+ }
+ Q_ASSERT(array);
+ return array;
+}
- (void)updateTableModel
{
- QAccessibleInterface *iface = QAccessible::accessibleInterface(axid);
- if (iface && iface->isValid()) {
+ if (QAccessibleInterface *iface = self.qtInterface) {
if (QAccessibleTableInterface *table = iface->tableInterface()) {
Q_ASSERT(!self.isManagedByParent);
+ qCDebug(lcAccessibilityTable) << "Updating table representation with"
+ << table->rowCount() << table->columnCount();
rows = [self populateTableArray:rows role:NSAccessibilityRowRole count:table->rowCount()];
columns = [self populateTableArray:columns role:NSAccessibilityColumnRole count:table->columnCount()];
}
}
}
+- (QAccessibleInterface *)qtInterface
+{
+ QAccessibleInterface *iface = QAccessible::accessibleInterface(axid);
+ if (!iface || !iface->isValid())
+ return nullptr;
+
+ // If this is a placeholder element for a table cell, associate it with the
+ // cell interface (which will be created now, if needed). The current axid is
+ // for the table to which the cell belongs, so iface is pointing at the table.
+ if (synthesizedRole == NSAccessibilityCellRole) {
+ // get the cell interface - there must be a valid one
+ QAccessibleTableInterface *table = iface->tableInterface();
+ Q_ASSERT(table);
+ QAccessibleInterface *cell = table->cellAt(m_rowIndex, m_columnIndex);
+ if (!cell)
+ return nullptr;
+ Q_ASSERT(cell->isValid());
+ iface = cell;
+
+ // no longer a placeholder
+ axid = QAccessible::uniqueId(cell);
+ synthesizedRole = nil;
+
+ QAccessibleCache *cache = QAccessibleCache::instance();
+ if (QMacAccessibilityElement *cellElement = cache->elementForId(axid)) {
+ // there already is another, non-placeholder element in the cache
+ Q_ASSERT(cellElement->synthesizedRole == nil);
+ // we have to release it if it's not us
+ if (cellElement != self) {
+ // for the same cell position
+ Q_ASSERT(cellElement->m_rowIndex == m_rowIndex && cellElement->m_columnIndex == m_columnIndex);
+ [cellElement release];
+ }
+ }
+
+ cache->insertElement(axid, self);
+ }
+ return iface;
+}
+
//
// accessibility protocol
//
- (BOOL)isAccessibilityFocused
{
- QAccessibleInterface *iface = QAccessible::accessibleInterface(axid);
- if (!iface || !iface->isValid()) {
- return false;
- }
// Just check if the app thinks we're focused.
id focusedElement = NSApp.accessibilityApplicationFocusedUIElement;
return [focusedElement isEqual:self];
@@ -240,31 +384,33 @@ static void convertLineOffset(QAccessibleTextInterface *text, int *line, int *of
}
- (NSString *) accessibilityRole {
- QAccessibleInterface *iface = QAccessible::accessibleInterface(axid);
- if (!iface || !iface->isValid())
- return NSAccessibilityUnknownRole;
+ // shortcut for cells, rows, and columns in a table
if (synthesizedRole)
return synthesizedRole;
- return QCocoaAccessible::macRole(iface);
+ if (QAccessibleInterface *iface = self.qtInterface)
+ return QCocoaAccessible::macRole(iface);
+ return NSAccessibilityUnknownRole;
}
- (NSString *) accessibilitySubRole {
- QAccessibleInterface *iface = QAccessible::accessibleInterface(axid);
- if (!iface || !iface->isValid())
- return NSAccessibilityUnknownRole;
- return QCocoaAccessible::macSubrole(iface);
+ if (QAccessibleInterface *iface = self.qtInterface)
+ return QCocoaAccessible::macSubrole(iface);
+ return NSAccessibilityUnknownRole;
}
- (NSString *) accessibilityRoleDescription {
- QAccessibleInterface *iface = QAccessible::accessibleInterface(axid);
- if (!iface || !iface->isValid())
- return NSAccessibilityUnknownRole;
- return NSAccessibilityRoleDescription(self.accessibilityRole, self.accessibilitySubRole);
+ if (QAccessibleInterface *iface = self.qtInterface)
+ return NSAccessibilityRoleDescription(self.accessibilityRole, self.accessibilitySubRole);
+ return NSAccessibilityUnknownRole;
}
- (NSArray *) accessibilityChildren {
- QAccessibleInterface *iface = QAccessible::accessibleInterface(axid);
- if (!iface || !iface->isValid())
+ // shortcut for cells
+ if (synthesizedRole == NSAccessibilityCellRole)
+ return nil;
+
+ QAccessibleInterface *iface = self.qtInterface;
+ if (!iface)
return nil;
if (QAccessibleTableInterface *table = iface->tableInterface()) {
// either a table or table rows/columns
@@ -320,30 +466,39 @@ static void convertLineOffset(QAccessibleTextInterface *text, int *line, int *of
} else if (synthesizedRole == NSAccessibilityRowRole) {
// axid matches the parent table axid so that we can easily find the parent table
// children of row are cell/any items
- QMacAccessibilityElement *tableElement = [QMacAccessibilityElement elementWithId:axid];
- Q_ASSERT(tableElement->rows);
- NSUInteger rowIndex = [tableElement->rows indexOfObjectIdenticalTo:self];
- Q_ASSERT(rowIndex != NSNotFound);
- int numColumns = table->columnCount();
- NSMutableArray<QMacAccessibilityElement *> *cells =
- [NSMutableArray<QMacAccessibilityElement *> arrayWithCapacity:numColumns];
- for (int i = 0; i < numColumns; ++i) {
- QAccessibleInterface *cell = table->cellAt(rowIndex, i);
- if (cell && cell->isValid()) {
- QAccessible::Id cellId = QAccessible::uniqueId(cell);
- QMacAccessibilityElement *element =
- [QMacAccessibilityElement elementWithId:cellId];
- if (element) {
- [cells addObject:element];
- }
- }
- }
- return NSAccessibilityUnignoredChildren(cells);
+ Q_ASSERT(m_rowIndex >= 0);
+ const int numColumns = table->columnCount();
+ columns = [self populateTableRow:columns count:numColumns];
+ return NSAccessibilityUnignoredChildren(columns);
}
}
return QCocoaAccessible::unignoredChildren(iface);
}
+- (NSArray *) accessibilitySelectedChildren {
+ QAccessibleInterface *iface = QAccessible::accessibleInterface(axid);
+ if (!iface || !iface->isValid())
+ return nil;
+
+ QAccessibleSelectionInterface *selection = iface->selectionInterface();
+ if (!selection)
+ return nil;
+
+ const QList<QAccessibleInterface *> selectedList = selection->selectedItems();
+ const qsizetype numSelected = selectedList.size();
+ NSMutableArray<QMacAccessibilityElement *> *selectedChildren =
+ [NSMutableArray<QMacAccessibilityElement *> arrayWithCapacity:numSelected];
+ for (QAccessibleInterface *selectedChild : selectedList) {
+ if (selectedChild && selectedChild->isValid()) {
+ QAccessible::Id id = QAccessible::uniqueId(selectedChild);
+ QMacAccessibilityElement *element = [QMacAccessibilityElement elementWithId:id];
+ if (element)
+ [selectedChildren addObject:element];
+ }
+ }
+ return NSAccessibilityUnignoredChildren(selectedChildren);
+}
+
- (id) accessibilityWindow {
// We're in the same window as our parent.
return [self.accessibilityParent accessibilityWindow];
@@ -355,26 +510,41 @@ static void convertLineOffset(QAccessibleTextInterface *text, int *line, int *of
}
- (NSString *) accessibilityTitle {
- QAccessibleInterface *iface = QAccessible::accessibleInterface(axid);
- if (!iface || !iface->isValid())
- return nil;
- if (iface->role() == QAccessible::StaticText)
- return nil;
- if (self.isManagedByParent)
- return nil;
- return iface->text(QAccessible::Name).toNSString();
+ if (QAccessibleInterface *iface = self.qtInterface) {
+ if (iface->role() == QAccessible::StaticText)
+ return nil;
+ if (self.isManagedByParent)
+ return nil;
+ return iface->text(QAccessible::Name).toNSString();
+ }
+ return nil;
+}
+
+- (NSString*) accessibilityIdentifier {
+ if (QAccessibleInterface *iface = self.qtInterface)
+ return QAccessibleBridgeUtils::accessibleId(iface).toNSString();
+ return nil;
}
- (BOOL) isAccessibilityEnabled {
- QAccessibleInterface *iface = QAccessible::accessibleInterface(axid);
- if (!iface || !iface->isValid())
- return false;
- return !iface->state().disabled;
+ if (QAccessibleInterface *iface = self.qtInterface)
+ return !iface->state().disabled;
+ return false;
}
- (id)accessibilityParent {
- QAccessibleInterface *iface = QAccessible::accessibleInterface(axid);
- if (!iface || !iface->isValid())
+ if (synthesizedRole == NSAccessibilityCellRole) {
+ // a synthetic cell without interface - shortcut to the row
+ QMacAccessibilityElement *tableElement =
+ [QMacAccessibilityElement elementWithId:axid];
+ Q_ASSERT(tableElement && tableElement->rows);
+ Q_ASSERT(int(tableElement->rows.count) > m_rowIndex);
+ QMacAccessibilityElement *rowElement = tableElement->rows[m_rowIndex];
+ return rowElement;
+ }
+
+ QAccessibleInterface *iface = self.qtInterface;
+ if (!iface)
return nil;
if (self.isManagedByParent) {
@@ -389,23 +559,23 @@ static void convertLineOffset(QAccessibleTextInterface *text, int *line, int *of
if (QAccessibleInterface *parent = iface->parent()) {
if (parent->tableInterface()) {
- if (QAccessibleTableCellInterface *cell = iface->tableCellInterface()) {
- // parent of cell should be row
- QAccessible::Id parentId = QAccessible::uniqueId(parent);
- QMacAccessibilityElement *tableElement =
- [QMacAccessibilityElement elementWithId:parentId];
-
- const int rowIndex = cell->rowIndex();
- if (tableElement->rows && int([tableElement->rows count]) > rowIndex) {
- QMacAccessibilityElement *rowElement = tableElement->rows[rowIndex];
- return NSAccessibilityUnignoredAncestor(rowElement);
- }
- }
- }
- if (parent->role() != QAccessible::Application) {
- QAccessible::Id parentId = QAccessible::uniqueId(parent);
- return NSAccessibilityUnignoredAncestor([QMacAccessibilityElement elementWithId: parentId]);
+ QMacAccessibilityElement *tableElement =
+ [QMacAccessibilityElement elementWithInterface:parent];
+
+ // parent of cell should be row
+ int rowIndex = -1;
+ if (m_rowIndex >= 0 && m_columnIndex >= 0)
+ rowIndex = m_rowIndex;
+ else if (QAccessibleTableCellInterface *cell = iface->tableCellInterface())
+ rowIndex = cell->rowIndex();
+ Q_ASSERT(tableElement->rows);
+ if (rowIndex > int([tableElement->rows count]) || rowIndex == -1)
+ return nil;
+ QMacAccessibilityElement *rowElement = tableElement->rows[rowIndex];
+ return NSAccessibilityUnignoredAncestor(rowElement);
}
+ if (parent->role() != QAccessible::Application)
+ return NSAccessibilityUnignoredAncestor([QMacAccessibilityElement elementWithInterface: parent]);
}
if (QWindow *window = iface->window()) {
@@ -419,8 +589,8 @@ static void convertLineOffset(QAccessibleTextInterface *text, int *line, int *of
}
- (NSRect)accessibilityFrame {
- QAccessibleInterface *iface = QAccessible::accessibleInterface(axid);
- if (!iface || !iface->isValid())
+ QAccessibleInterface *iface = self.qtInterface;
+ if (!iface)
return NSZeroRect;
QRect rect;
@@ -437,10 +607,7 @@ static void convertLineOffset(QAccessibleTextInterface *text, int *line, int *of
int &row = isRow ? cellPos.ry() : cellPos.rx();
int &col = isRow ? cellPos.rx() : cellPos.ry();
- QMacAccessibilityElement *tableElement =
- [QMacAccessibilityElement elementWithId:axid];
- NSArray *tracks = isRow ? tableElement->rows : tableElement->columns;
- NSUInteger trackIndex = [tracks indexOfObjectIdenticalTo:self];
+ NSUInteger trackIndex = self.accessibilityIndex;
if (trackIndex != NSNotFound) {
row = int(trackIndex);
if (QAccessibleInterface *firstCell = table->cellAt(cellPos.y(), cellPos.x())) {
@@ -463,71 +630,50 @@ static void convertLineOffset(QAccessibleTextInterface *text, int *line, int *of
}
- (NSString*)accessibilityLabel {
- QAccessibleInterface *iface = QAccessible::accessibleInterface(axid);
- if (!iface || !iface->isValid()) {
- qWarning() << "Called accessibilityLabel on invalid object: " << axid;
- return nil;
- }
- return iface->text(QAccessible::Description).toNSString();
-}
-
-- (void)setAccessibilityLabel:(NSString*)label{
- QAccessibleInterface *iface = QAccessible::accessibleInterface(axid);
- if (!iface || !iface->isValid())
- return;
- iface->setText(QAccessible::Description, QString::fromNSString(label));
-}
-
-- (id) accessibilityMinValue:(QAccessibleInterface*)iface {
- if (QAccessibleValueInterface *val = iface->valueInterface())
- return @(val->minimumValue().toDouble());
+ if (QAccessibleInterface *iface = self.qtInterface)
+ return iface->text(QAccessible::Description).toNSString();
+ qWarning() << "Called accessibilityLabel on invalid object: " << axid;
return nil;
}
-- (id) accessibilityMaxValue:(QAccessibleInterface*)iface {
- if (QAccessibleValueInterface *val = iface->valueInterface())
- return @(val->maximumValue().toDouble());
- return nil;
+- (void)setAccessibilityLabel:(NSString*)label{
+ if (QAccessibleInterface *iface = self.qtInterface)
+ iface->setText(QAccessible::Description, QString::fromNSString(label));
}
- (id) accessibilityValue {
- QAccessibleInterface *iface = QAccessible::accessibleInterface(axid);
- if (!iface || !iface->isValid())
- return nil;
-
- // VoiceOver asks for the value attribute for all elements. Return nil
- // if we don't want the element to have a value attribute.
- if (!QCocoaAccessible::hasValueAttribute(iface))
- return nil;
-
- return QCocoaAccessible::getValueAttribute(iface);
+ if (QAccessibleInterface *iface = self.qtInterface) {
+ // VoiceOver asks for the value attribute for all elements. Return nil
+ // if we don't want the element to have a value attribute.
+ if (QCocoaAccessible::hasValueAttribute(iface))
+ return QCocoaAccessible::getValueAttribute(iface);
+ }
+ return nil;
}
- (NSInteger) accessibilityNumberOfCharacters {
- QAccessibleInterface *iface = QAccessible::accessibleInterface(axid);
- if (!iface || !iface->isValid())
- return 0;
- if (QAccessibleTextInterface *text = iface->textInterface())
- return text->characterCount();
+ if (QAccessibleInterface *iface = self.qtInterface) {
+ if (QAccessibleTextInterface *text = iface->textInterface())
+ return text->characterCount();
+ }
return 0;
}
- (NSString *) accessibilitySelectedText {
- QAccessibleInterface *iface = QAccessible::accessibleInterface(axid);
- if (!iface || !iface->isValid())
- return nil;
- if (QAccessibleTextInterface *text = iface->textInterface()) {
- int start = 0;
- int end = 0;
- text->selection(0, &start, &end);
- return text->text(start, end).toNSString();
+ if (QAccessibleInterface *iface = self.qtInterface) {
+ if (QAccessibleTextInterface *text = iface->textInterface()) {
+ int start = 0;
+ int end = 0;
+ text->selection(0, &start, &end);
+ return text->text(start, end).toNSString();
+ }
}
return nil;
}
- (NSRange) accessibilitySelectedTextRange {
- QAccessibleInterface *iface = QAccessible::accessibleInterface(axid);
- if (!iface || !iface->isValid())
+ QAccessibleInterface *iface = self.qtInterface;
+ if (!iface)
return NSRange();
if (QAccessibleTextInterface *text = iface->textInterface()) {
int start = 0;
@@ -544,8 +690,8 @@ static void convertLineOffset(QAccessibleTextInterface *text, int *line, int *of
}
- (NSInteger)accessibilityLineForIndex:(NSInteger)index {
- QAccessibleInterface *iface = QAccessible::accessibleInterface(axid);
- if (!iface || !iface->isValid())
+ QAccessibleInterface *iface = self.qtInterface;
+ if (!iface)
return 0;
if (QAccessibleTextInterface *text = iface->textInterface()) {
QString textToPos = text->text(0, index);
@@ -555,8 +701,8 @@ static void convertLineOffset(QAccessibleTextInterface *text, int *line, int *of
}
- (NSRange)accessibilityVisibleCharacterRange {
- QAccessibleInterface *iface = QAccessible::accessibleInterface(axid);
- if (!iface || !iface->isValid())
+ QAccessibleInterface *iface = self.qtInterface;
+ if (!iface)
return NSRange();
// FIXME This is not correct and may impact performance for big texts
if (QAccessibleTextInterface *text = iface->textInterface())
@@ -565,8 +711,8 @@ static void convertLineOffset(QAccessibleTextInterface *text, int *line, int *of
}
- (NSInteger) accessibilityInsertionPointLineNumber {
- QAccessibleInterface *iface = QAccessible::accessibleInterface(axid);
- if (!iface || !iface->isValid())
+ QAccessibleInterface *iface = self.qtInterface;
+ if (!iface)
return 0;
if (QAccessibleTextInterface *text = iface->textInterface()) {
int position = text->cursorPosition();
@@ -577,8 +723,8 @@ static void convertLineOffset(QAccessibleTextInterface *text, int *line, int *of
- (NSArray *)accessibilityParameterizedAttributeNames {
- QAccessibleInterface *iface = QAccessible::accessibleInterface(axid);
- if (!iface || !iface->isValid()) {
+ QAccessibleInterface *iface = self.qtInterface;
+ if (!iface) {
qWarning() << "Called attribute on invalid object: " << axid;
return nil;
}
@@ -601,8 +747,8 @@ static void convertLineOffset(QAccessibleTextInterface *text, int *line, int *of
}
- (id)accessibilityAttributeValue:(NSString *)attribute forParameter:(id)parameter {
- QAccessibleInterface *iface = QAccessible::accessibleInterface(axid);
- if (!iface || !iface->isValid()) {
+ QAccessibleInterface *iface = self.qtInterface;
+ if (!iface) {
qWarning() << "Called attribute on invalid object: " << axid;
return nil;
}
@@ -642,7 +788,7 @@ static void convertLineOffset(QAccessibleTextInterface *text, int *line, int *of
QRectF rect;
if (range.length > 0) {
NSUInteger position = range.location + range.length - 1;
- if (position > range.location && iface->textInterface()->text(position, position + 1) == QStringLiteral("\n"))
+ if (position > range.location && iface->textInterface()->text(position, position + 1) == "\n"_L1)
--position;
QRect lastRect = iface->textInterface()->characterRect(position);
rect = firstRect.united(lastRect);
@@ -670,8 +816,8 @@ static void convertLineOffset(QAccessibleTextInterface *text, int *line, int *of
}
- (BOOL)accessibilityIsAttributeSettable:(NSString *)attribute {
- QAccessibleInterface *iface = QAccessible::accessibleInterface(axid);
- if (!iface || !iface->isValid())
+ QAccessibleInterface *iface = self.qtInterface;
+ if (!iface)
return NO;
if ([attribute isEqualToString:NSAccessibilityFocusedAttribute]) {
@@ -689,8 +835,8 @@ static void convertLineOffset(QAccessibleTextInterface *text, int *line, int *of
}
- (void)accessibilitySetValue:(id)value forAttribute:(NSString *)attribute {
- QAccessibleInterface *iface = QAccessible::accessibleInterface(axid);
- if (!iface || !iface->isValid())
+ QAccessibleInterface *iface = self.qtInterface;
+ if (!iface)
return;
if ([attribute isEqualToString:NSAccessibilityFocusedAttribute]) {
if (QAccessibleActionInterface *action = iface->actionInterface())
@@ -718,8 +864,8 @@ static void convertLineOffset(QAccessibleTextInterface *text, int *line, int *of
- (NSArray *)accessibilityActionNames {
NSMutableArray *nsActions = [[NSMutableArray new] autorelease];
- QAccessibleInterface *iface = QAccessible::accessibleInterface(axid);
- if (!iface || !iface->isValid())
+ QAccessibleInterface *iface = self.qtInterface;
+ if (!iface)
return nsActions;
const QStringList &supportedActionNames = QAccessibleBridgeUtils::effectiveActionNames(iface);
@@ -733,8 +879,8 @@ static void convertLineOffset(QAccessibleTextInterface *text, int *line, int *of
}
- (NSString *)accessibilityActionDescription:(NSString *)action {
- QAccessibleInterface *iface = QAccessible::accessibleInterface(axid);
- if (!iface || !iface->isValid())
+ QAccessibleInterface *iface = self.qtInterface;
+ if (!iface)
return nil; // FIXME is that the right return type??
QString qtAction = QCocoaAccessible::translateAction(action, iface);
QString description;
@@ -751,8 +897,7 @@ static void convertLineOffset(QAccessibleTextInterface *text, int *line, int *of
}
- (void)accessibilityPerformAction:(NSString *)action {
- QAccessibleInterface *iface = QAccessible::accessibleInterface(axid);
- if (iface && iface->isValid()) {
+ if (QAccessibleInterface *iface = self.qtInterface) {
const QString qtAction = QCocoaAccessible::translateAction(action, iface);
QAccessibleBridgeUtils::performEffectiveAction(iface, qtAction);
}
@@ -761,15 +906,20 @@ static void convertLineOffset(QAccessibleTextInterface *text, int *line, int *of
// misc
- (BOOL)accessibilityIsIgnored {
- QAccessibleInterface *iface = QAccessible::accessibleInterface(axid);
- if (!iface || !iface->isValid())
- return true;
- return QCocoaAccessible::shouldBeIgnored(iface);
+ // Short-cut for placeholders and synthesized elements. Working around a bug
+ // that corrups lists returned by NSAccessibilityUnignoredChildren, otherwise
+ // we could ignore rows and columns that are outside the table.
+ if (self.isManagedByParent)
+ return false;
+
+ if (QAccessibleInterface *iface = self.qtInterface)
+ return QCocoaAccessible::shouldBeIgnored(iface);
+ return true;
}
- (id)accessibilityHitTest:(NSPoint)point {
- QAccessibleInterface *iface = QAccessible::accessibleInterface(axid);
- if (!iface || !iface->isValid()) {
+ QAccessibleInterface *iface = self.qtInterface;
+ if (!iface) {
// qDebug("Hit test: INVALID");
return NSAccessibilityUnignoredAncestor(self);
}
@@ -788,26 +938,23 @@ static void convertLineOffset(QAccessibleTextInterface *text, int *line, int *of
childInterface = childOfChildInterface;
} while (childOfChildInterface && childOfChildInterface->isValid());
- QAccessible::Id childId = QAccessible::uniqueId(childInterface);
// hit a child, forward to child accessible interface.
- QMacAccessibilityElement *accessibleElement = [QMacAccessibilityElement elementWithId:childId];
+ QMacAccessibilityElement *accessibleElement = [QMacAccessibilityElement elementWithInterface:childInterface];
if (accessibleElement)
return NSAccessibilityUnignoredAncestor(accessibleElement);
return NSAccessibilityUnignoredAncestor(self);
}
- (id)accessibilityFocusedUIElement {
- QAccessibleInterface *iface = QAccessible::accessibleInterface(axid);
-
- if (!iface || !iface->isValid()) {
+ QAccessibleInterface *iface = self.qtInterface;
+ if (!iface) {
qWarning("FocusedUIElement for INVALID");
return nil;
}
QAccessibleInterface *childInterface = iface->focusChild();
if (childInterface && childInterface->isValid()) {
- QAccessible::Id childAxid = QAccessible::uniqueId(childInterface);
- QMacAccessibilityElement *accessibleElement = [QMacAccessibilityElement elementWithId:childAxid];
+ QMacAccessibilityElement *accessibleElement = [QMacAccessibilityElement elementWithInterface:childInterface];
return NSAccessibilityUnignoredAncestor(accessibleElement);
}
@@ -815,8 +962,7 @@ static void convertLineOffset(QAccessibleTextInterface *text, int *line, int *of
}
- (NSString *) accessibilityHelp {
- QAccessibleInterface *iface = QAccessible::accessibleInterface(axid);
- if (iface && iface->isValid()) {
+ if (QAccessibleInterface *iface = self.qtInterface) {
const QString helpText = iface->text(QAccessible::Help);
if (!helpText.isEmpty())
return helpText.toNSString();
@@ -829,19 +975,17 @@ static void convertLineOffset(QAccessibleTextInterface *text, int *line, int *of
*/
- (NSInteger) accessibilityIndex {
NSInteger index = 0;
- QAccessibleInterface *iface = QAccessible::accessibleInterface(axid);
- if (iface && iface->isValid()) {
+ if (synthesizedRole == NSAccessibilityCellRole)
+ return m_columnIndex;
+ if (QAccessibleInterface *iface = self.qtInterface) {
if (self.isManagedByParent) {
// axid matches the parent table axid so that we can easily find the parent table
// children of row are cell/any items
if (QAccessibleTableInterface *table = iface->tableInterface()) {
- QMacAccessibilityElement *tableElement = [QMacAccessibilityElement elementWithId:axid];
- NSArray *track = synthesizedRole == NSAccessibilityRowRole
- ? tableElement->rows : tableElement->columns;
- if (track) {
- NSUInteger trackIndex = [track indexOfObjectIdenticalTo:self];
- index = (NSInteger)trackIndex;
- }
+ if (m_rowIndex >= 0)
+ index = NSInteger(m_rowIndex);
+ else if (m_columnIndex >= 0)
+ index = NSInteger(m_columnIndex);
}
}
}
@@ -849,18 +993,18 @@ static void convertLineOffset(QAccessibleTextInterface *text, int *line, int *of
}
- (NSArray *) accessibilityRows {
- QAccessibleInterface *iface = QAccessible::accessibleInterface(axid);
- if (iface && iface->isValid() && iface->tableInterface() && !synthesizedRole) {
- if (rows)
+ if (!synthesizedRole && rows) {
+ QAccessibleInterface *iface = self.qtInterface;
+ if (iface && iface->tableInterface())
return NSAccessibilityUnignoredChildren(rows);
}
return nil;
}
- (NSArray *) accessibilityColumns {
- QAccessibleInterface *iface = QAccessible::accessibleInterface(axid);
- if (iface && iface->isValid() && iface->tableInterface() && !synthesizedRole) {
- if (columns)
+ if (!synthesizedRole && columns) {
+ QAccessibleInterface *iface = self.qtInterface;
+ if (iface && iface->tableInterface())
return NSAccessibilityUnignoredChildren(columns);
}
return nil;