5#include <AppKit/AppKit.h>
13#include <QtCore/qlogging.h>
14#include <QtGui/private/qaccessiblecache_p.h>
15#include <QtGui/private/qaccessiblebridgeutils_p.h>
16#include <QtGui/qaccessible.h>
20Q_STATIC_LOGGING_CATEGORY(lcAccessibilityTable,
"qt.accessibility.table")
22using namespace Qt::StringLiterals;
24#if QT_CONFIG(accessibility)
27
28
29
30
31
32
33
34
35
36
37
38
39static void convertLineOffset(QAccessibleTextInterface *text,
int *line,
int *offset, NSUInteger *start = 0, NSUInteger *end = 0)
41 Q_ASSERT(*line == -1 || *offset == -1);
42 Q_ASSERT(*line != -1 || *offset != -1);
43 Q_ASSERT(*offset <= text->characterCount());
46 int curStart = 0, curEnd = 0;
50 text->textAtOffset(curStart, QAccessible::LineBoundary, &curStart, &curEnd);
52 if (curStart == -1 || curEnd == -1) {
66 text->textAtOffset(curEnd, QAccessible::LineBoundary, &nextStart, &nextEnd);
67 if (nextEnd == curEnd)
70 }
while ((*line == -1 || curLine < *line) && (*offset == -1 || (curEnd <= *offset)) && curEnd <= text->characterCount());
72 curEnd = qMin(curEnd, text->characterCount());
79 Q_ASSERT(curStart >= 0);
80 Q_ASSERT(curEnd >= 0);
87@implementation QMacAccessibilityElement {
93 NSMutableArray<QMacAccessibilityElement *> *rows;
94 NSMutableArray<QMacAccessibilityElement *> *columns;
102 NSString *synthesizedRole;
105- (instancetype)initWithId:(QAccessible::Id)anId
107 return [self initWithId:anId role:nil];
110- (instancetype)initWithId:(QAccessible::Id)anId role:(NSAccessibilityRole)role
112 Q_ASSERT((
int)anId < 0);
120 synthesizedRole = role;
124 if (!synthesizedRole) {
125 if (QAccessibleInterface *iface = QAccessible::accessibleInterface(axid)) {
126 if (iface->tableInterface()) {
127 [self updateTableModel];
128 }
else if (
const auto *cell = iface->tableCellInterface()) {
131 m_rowIndex = cell->rowIndex();
132 m_columnIndex = cell->columnIndex();
133 QAccessibleInterface *table = cell->table();
135 QAccessibleTableInterface *tableInterface = table->tableInterface();
136 if (tableInterface) {
137 auto *tableElement = [QMacAccessibilityElement elementWithInterface:table];
138 Q_ASSERT(tableElement);
139 if (!tableElement->rows
140 ||
int(tableElement->rows.count) <= m_rowIndex
141 ||
int(tableElement->rows.count) != tableInterface->rowCount()) {
142 qCWarning(lcAccessibilityTable)
143 <<
"Cell requested for row" << m_rowIndex <<
"is out of"
144 <<
"bounds for table with" << (tableElement->rows ?
145 tableElement->rows.count : tableInterface->rowCount())
146 <<
"rows! Resizing table model.";
147 [tableElement updateTableModel];
150 Q_ASSERT(tableElement->rows);
151 Q_ASSERT(
int(tableElement->rows.count) > m_rowIndex);
153 auto *rowElement = tableElement->rows[m_rowIndex];
154 if (!rowElement->columns ||
int(rowElement->columns.count) != tableInterface->columnCount()) {
155 if (rowElement->columns) {
156 qCWarning(lcAccessibilityTable)
157 <<
"Table representation column count is out of sync:"
158 << rowElement->columns.count <<
"!=" << tableInterface->columnCount();
159 [rowElement->columns autorelease];
160 rowElement->columns = nil;
162 rowElement->columns = [rowElement populateTableRow:tableInterface->columnCount()];
163 [rowElement->columns retain];
166 qCDebug(lcAccessibilityTable) <<
"Creating cell representation for"
167 << m_rowIndex << m_columnIndex
169 << tableElement->rows.count <<
"rows and"
170 << rowElement->columns.count <<
"columns";
172 rowElement->columns[m_columnIndex] = self;
183
184
185
186
187
188
189
190
191+ (instancetype)elementWithId:(QAccessible::Id)anId
197 QAccessibleCache *cache = QAccessibleCache::instance();
199 QMacAccessibilityElement *element = cache->elementForId(anId);
201 Q_ASSERT(QAccessible::accessibleInterface(anId));
202 element = [[self alloc] initWithId:anId];
203 if (cache->insertElement(anId, element))
209+ (instancetype)elementWithInterface:(QAccessibleInterface *)iface
215 const QAccessible::Id anId = QAccessible::uniqueId(iface);
216 return [self elementWithId:anId];
219+ (
void)removeElementsFromCache:(NSArray *)array {
220 for (uint i = 0; i < array.count; ++i) {
221 QMacAccessibilityElement *cell = [array objectAtIndex:i];
223 QAccessibleCache::instance()->deleteInterface(cell->axid);
232 [QMacAccessibilityElement removeElementsFromCache:rows];
237 [QMacAccessibilityElement removeElementsFromCache:columns];
238 [columns autorelease];
241 synthesizedRole = nil;
243 NSAccessibilityPostNotification(self, NSAccessibilityUIElementDestroyedNotification);
247
248
249
250
251
252
253
254
255
256
259 [QMacAccessibilityElement removeElementsFromCache:rows];
263 [QMacAccessibilityElement removeElementsFromCache:columns];
266 QAccessibleCache::instance()->deleteInterface(axid);
270- (BOOL)isEqual:(id)object {
271 if ([object isKindOfClass:[QMacAccessibilityElement
class]]) {
272 QMacAccessibilityElement *other = object;
273 return other->axid == axid && other->synthesizedRole == synthesizedRole;
283- (BOOL)isManagedByParent {
284 return synthesizedRole != nil;
287- (NSMutableArray *)populateTableArray:(NSAccessibilityRole)role count:(
int)count
289 if (self.qtInterface) {
290 auto *array = [NSMutableArray<QMacAccessibilityElement *> arrayWithCapacity:count];
292 for (
int n = 0; n < count; ++n) {
294 QMacAccessibilityElement *element =
295 [[QMacAccessibilityElement alloc] initWithId:axid role:role];
297 if (role == NSAccessibilityRowRole)
298 element->m_rowIndex = n;
299 else if (role == NSAccessibilityColumnRole)
300 element->m_columnIndex = n;
301 [array addObject:element];
304 qWarning(
"QCocoaAccessibility: invalid child");
312- (NSMutableArray *)populateTableRow:(
int)count
314 Q_ASSERT(synthesizedRole == NSAccessibilityRowRole);
315 qCDebug(lcAccessibilityTable) <<
"Populating table row" << m_rowIndex
316 <<
"with" << count <<
"placeholder cells";
325 auto *array = [NSMutableArray<QMacAccessibilityElement *> arrayWithCapacity:count];
328 for (
int n = 0; n < count; ++n) {
330 QMacAccessibilityElement *cell =
331 [[QMacAccessibilityElement alloc] initWithId:axid role:NSAccessibilityCellRole];
333 cell->m_rowIndex = m_rowIndex;
334 cell->m_columnIndex = n;
335 [array addObject:cell];
342- (
void)updateTableModel
344 if (QAccessibleInterface *iface = self.qtInterface) {
345 if (QAccessibleTableInterface *table = iface->tableInterface()) {
346 Q_ASSERT(!self.isManagedByParent);
347 qCDebug(lcAccessibilityTable) <<
"Updating table representation with"
348 << table->rowCount() << table->columnCount();
353 rows = [self populateTableArray:NSAccessibilityRowRole count:table->rowCount()];
356 [columns autorelease];
359 columns = [self populateTableArray:NSAccessibilityColumnRole count:table->columnCount()];
365- (QAccessibleInterface *)qtInterface
367 QAccessibleInterface *iface = QAccessible::accessibleInterface(axid);
368 if (!iface || !iface->isValid())
374 if (synthesizedRole == NSAccessibilityCellRole) {
376 QAccessibleTableInterface *table = iface->tableInterface();
378 QAccessibleInterface *cell = table->cellAt(m_rowIndex, m_columnIndex);
381 Q_ASSERT(cell->isValid());
385 axid = QAccessible::uniqueId(cell);
386 synthesizedRole = nil;
388 QAccessibleCache *cache = QAccessibleCache::instance();
389 if (QMacAccessibilityElement *cellElement = cache->elementForId(axid)) {
391 Q_ASSERT(cellElement->synthesizedRole == nil);
393 if (cellElement != self) {
395 Q_ASSERT(cellElement->m_rowIndex == m_rowIndex && cellElement->m_columnIndex == m_columnIndex);
399 cache->insertElement(axid, self);
408- (BOOL)isAccessibilityFocused
411 id focusedElement = NSApp.accessibilityApplicationFocusedUIElement;
412 return [focusedElement isEqual:self];
417+ (id) lineNumberForIndex: (
int)index forText:(
const QString &)text
419 auto textBefore = QStringView(text).left(index);
420 qsizetype newlines = textBefore.count(u'\n');
424- (BOOL) accessibilityNotifiesWhenDestroyed {
428- (NSString *) accessibilityRole {
431 return synthesizedRole;
432 if (QAccessibleInterface *iface = self.qtInterface)
433 return QCocoaAccessible::macRole(iface);
434 return NSAccessibilityUnknownRole;
437- (NSString *) accessibilitySubRole {
438 if (QAccessibleInterface *iface = self.qtInterface)
439 return QCocoaAccessible::macSubrole(iface);
440 return NSAccessibilityUnknownRole;
443- (NSString *) accessibilityRoleDescription {
444 if (self.qtInterface)
445 return NSAccessibilityRoleDescription(self.accessibilityRole, self.accessibilitySubRole);
446 return NSAccessibilityUnknownRole;
449- (NSArray *) accessibilityChildren {
451 if (synthesizedRole == NSAccessibilityCellRole)
454 QAccessibleInterface *iface = self.qtInterface;
457 if (QAccessibleTableInterface *table = iface->tableInterface()) {
459 if (!synthesizedRole) {
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492 NSArray *rs = [self accessibilityRows];
493 NSArray *cs = [self accessibilityColumns];
494 const int rCount =
int([rs count]);
495 const int cCount =
int([cs count]);
496 int childCount = rCount + cCount;
497 NSMutableArray<QMacAccessibilityElement *> *tableChildren =
498 [NSMutableArray<QMacAccessibilityElement *> arrayWithCapacity:childCount];
499 for (
int i = 0; i < rCount; ++i) {
500 [tableChildren addObject:[rs objectAtIndex:i]];
502 for (
int i = 0; i < cCount; ++i) {
503 [tableChildren addObject:[cs objectAtIndex:i]];
505 return NSAccessibilityUnignoredChildren(tableChildren);
506 }
else if (synthesizedRole == NSAccessibilityColumnRole) {
508 }
else if (synthesizedRole == NSAccessibilityRowRole) {
511 Q_ASSERT(m_rowIndex >= 0);
512 Q_ASSERT(rows == nil);
513 const unsigned int numColumns = table->columnCount();
514 if (!columns || columns.count != numColumns) {
516 [columns autorelease];
519 columns = [self populateTableRow:numColumns];
522 return NSAccessibilityUnignoredChildren(columns);
525 return QCocoaAccessible::unignoredChildren(iface);
528- (NSArray *) accessibilitySelectedChildren {
529 QAccessibleInterface *iface = QAccessible::accessibleInterface(axid);
530 if (!iface || !iface->isValid())
533 QAccessibleSelectionInterface *selection = iface->selectionInterface();
537 const QList<QAccessibleInterface *> selectedList = selection->selectedItems();
538 const qsizetype numSelected = selectedList.size();
539 NSMutableArray<QMacAccessibilityElement *> *selectedChildren =
540 [NSMutableArray<QMacAccessibilityElement *> arrayWithCapacity:numSelected];
541 for (QAccessibleInterface *selectedChild : selectedList) {
542 if (selectedChild && selectedChild->isValid()) {
543 QAccessible::Id id = QAccessible::uniqueId(selectedChild);
544 QMacAccessibilityElement *element = [QMacAccessibilityElement elementWithId:id];
546 [selectedChildren addObject:element];
549 return NSAccessibilityUnignoredChildren(selectedChildren);
552- (id) accessibilityWindow {
554 NSAccessibilityElement *parent = self.accessibilityParent;
555 if (parent && parent.accessibilityRole == NSAccessibilityWindowRole)
557 return [parent accessibilityWindow];
560- (id) accessibilityTopLevelUIElementAttribute {
562 return [self.accessibilityParent accessibilityTopLevelUIElementAttribute];
565- (NSString *) accessibilityTitle {
566 if (QAccessibleInterface *iface = self.qtInterface) {
567 if (iface->role() == QAccessible::StaticText)
569 if (self.isManagedByParent)
571 return iface->text(QAccessible::Name).toNSString();
576- (id) accessibilityTitleUIElement {
577 QAccessibleInterface *iface = self.qtInterface;
581 const auto labelRelations = iface->relations(QAccessible::Label);
582 if (labelRelations.empty())
585 QAccessibleInterface *label = labelRelations.first().first;
589 QMacAccessibilityElement *accessibleElement = [QMacAccessibilityElement elementWithInterface:label];
590 if (!accessibleElement)
593 return NSAccessibilityUnignoredAncestor(accessibleElement);
596- (NSString*) accessibilityIdentifier {
597 if (QAccessibleInterface *iface = self.qtInterface)
598 return QAccessibleBridgeUtils::accessibleId(iface).toNSString();
602- (BOOL) isAccessibilityEnabled {
603 if (QAccessibleInterface *iface = self.qtInterface)
604 return !iface->state().disabled;
608- (id)accessibilityParent {
609 if (synthesizedRole == NSAccessibilityCellRole) {
611 QMacAccessibilityElement *tableElement =
612 [QMacAccessibilityElement elementWithId:axid];
613 Q_ASSERT(tableElement && tableElement->rows);
614 Q_ASSERT(
int(tableElement->rows.count) > m_rowIndex);
615 QMacAccessibilityElement *rowElement = tableElement->rows[m_rowIndex];
619 QAccessibleInterface *iface = self.qtInterface;
623 if (self.isManagedByParent) {
625 return NSAccessibilityUnignoredAncestor([QMacAccessibilityElement elementWithId:axid]);
628 if (QAccessibleInterface *parent = iface->parent()) {
629 if (parent->tableInterface()) {
630 QMacAccessibilityElement *tableElement =
631 [QMacAccessibilityElement elementWithInterface:parent];
635 if (m_rowIndex >= 0 && m_columnIndex >= 0)
636 rowIndex = m_rowIndex;
637 else if (QAccessibleTableCellInterface *cell = iface->tableCellInterface())
638 rowIndex = cell->rowIndex();
639 Q_ASSERT(tableElement->rows);
640 if (rowIndex >
int([tableElement->rows count]) || rowIndex == -1)
642 QMacAccessibilityElement *rowElement = tableElement->rows[rowIndex];
643 return NSAccessibilityUnignoredAncestor(rowElement);
650 if (parent->role() != QAccessible::Application && parent->role() != QAccessible::Window)
651 return NSAccessibilityUnignoredAncestor([QMacAccessibilityElement elementWithInterface: parent]);
654 if (QWindow *window = iface->window()) {
655 QPlatformWindow *platformWindow = window->handle();
656 if (platformWindow) {
657 QCocoaWindow *win =
static_cast<QCocoaWindow*>(platformWindow);
658 return NSAccessibilityUnignoredAncestor(qnsview_cast(win->view()));
664- (NSRect)accessibilityFrame {
665 QAccessibleInterface *iface = self.qtInterface;
670 if (self.isManagedByParent) {
671 if (QAccessibleTableInterface *table = iface->tableInterface()) {
678 const bool isRow = synthesizedRole == NSAccessibilityRowRole;
680 int &row = isRow ? cellPos.ry() : cellPos.rx();
681 int &col = isRow ? cellPos.rx() : cellPos.ry();
683 NSUInteger trackIndex = self.accessibilityIndex;
684 if (trackIndex != NSNotFound) {
685 row =
int(trackIndex);
686 if (QAccessibleInterface *firstCell = table->cellAt(cellPos.y(), cellPos.x())) {
687 rect = firstCell->rect();
688 col = isRow ? table->columnCount() : table->rowCount();
691 if (QAccessibleInterface *lastCell =
692 table->cellAt(cellPos.y(), cellPos.x()))
693 rect = rect.united(lastCell->rect());
699 rect = iface->rect();
702 return QCocoaScreen::mapToNative(rect);
705- (NSString*)accessibilityLabel {
706 if (QAccessibleInterface *iface = self.qtInterface)
707 return iface->text(QAccessible::Description).toNSString();
708 qWarning() <<
"Called accessibilityLabel on invalid object: " << axid;
712- (
void)setAccessibilityLabel:(NSString*)label{
713 if (QAccessibleInterface *iface = self.qtInterface)
714 iface->setText(QAccessible::Description, QString::fromNSString(label));
717- (id) accessibilityValue {
718 if (QAccessibleInterface *iface = self.qtInterface) {
721 if (QCocoaAccessible::hasValueAttribute(iface))
722 return QCocoaAccessible::getValueAttribute(iface);
728- (id) accessibilityMinValue {
729 if (QAccessibleInterface *iface = self.qtInterface) {
730 if (iface->valueInterface()) {
731 return iface->valueInterface()->minimumValue().toString().toNSString();
738- (id) accessibilityMaxValue {
739 if (QAccessibleInterface *iface = self.qtInterface) {
740 if (iface->valueInterface()) {
741 return iface->valueInterface()->maximumValue().toString().toNSString();
747- (NSInteger) accessibilityNumberOfCharacters {
748 if (QAccessibleInterface *iface = self.qtInterface) {
749 if (QAccessibleTextInterface *text = iface->textInterface())
750 return text->characterCount();
755- (NSString *) accessibilitySelectedText {
756 if (QAccessibleInterface *iface = self.qtInterface) {
757 if (QAccessibleTextInterface *text = iface->textInterface()) {
760 text->selection(0, &start, &end);
761 return text->text(start, end).toNSString();
767- (NSRange) accessibilitySelectedTextRange {
768 QAccessibleInterface *iface = self.qtInterface;
771 if (QAccessibleTextInterface *text = iface->textInterface()) {
774 if (text->selectionCount() > 0) {
775 text->selection(0, &start, &end);
777 start = text->cursorPosition();
780 return NSMakeRange(quint32(start), quint32(end - start));
782 return NSMakeRange(0, 0);
785- (NSInteger)accessibilityLineForIndex:(NSInteger)index {
786 QAccessibleInterface *iface = self.qtInterface;
789 if (QAccessibleTextInterface *text = iface->textInterface()) {
790 QString textToPos = text->text(0, index);
791 return textToPos.count(
'\n');
796- (NSRange)accessibilityVisibleCharacterRange {
797 QAccessibleInterface *iface = self.qtInterface;
801 if (QAccessibleTextInterface *text = iface->textInterface())
802 return NSMakeRange(0,
static_cast<uint>(text->characterCount()));
803 return NSMakeRange(0,
static_cast<uint>(iface->text(QAccessible::Name).length()));
806- (NSInteger) accessibilityInsertionPointLineNumber {
807 QAccessibleInterface *iface = self.qtInterface;
810 if (QAccessibleTextInterface *text = iface->textInterface()) {
811 int position = text->cursorPosition();
812 return [self accessibilityLineForIndex:position];
817- (NSArray *)accessibilityParameterizedAttributeNames {
819 QAccessibleInterface *iface = self.qtInterface;
821 qWarning() <<
"Called attribute on invalid object: " << axid;
825 if (iface->textInterface()) {
827 NSAccessibilityStringForRangeParameterizedAttribute,
828 NSAccessibilityLineForIndexParameterizedAttribute,
829 NSAccessibilityRangeForLineParameterizedAttribute,
830 NSAccessibilityRangeForPositionParameterizedAttribute,
832 NSAccessibilityBoundsForRangeParameterizedAttribute,
834 NSAccessibilityStyleRangeForIndexParameterizedAttribute,
835 NSAccessibilityAttributedStringForRangeParameterizedAttribute
842- (id)accessibilityAttributeValue:(NSString *)attribute forParameter:(id)parameter {
843 QAccessibleInterface *iface = self.qtInterface;
845 qWarning() <<
"Called attribute on invalid object: " << axid;
849 if (!iface->textInterface())
852 if ([attribute isEqualToString: NSAccessibilityStringForRangeParameterizedAttribute]) {
853 NSRange range = [parameter rangeValue];
854 QString text = iface->textInterface()->text(range.location, range.location + range.length);
855 return text.toNSString();
857 if ([attribute isEqualToString: NSAccessibilityLineForIndexParameterizedAttribute]) {
858 int index = [parameter intValue];
859 if (index < 0 || index > iface->textInterface()->characterCount())
862 if (iface->state().multiLine) {
864 convertLineOffset(iface->textInterface(), &line, &index);
868 if ([attribute isEqualToString: NSAccessibilityRangeForLineParameterizedAttribute]) {
869 int line = [parameter intValue];
873 NSUInteger startOffset = 0;
874 NSUInteger endOffset = 0;
875 convertLineOffset(iface->textInterface(), &line, &lineOffset, &startOffset, &endOffset);
876 return [NSValue valueWithRange:NSMakeRange(startOffset, endOffset - startOffset)];
878 if ([attribute isEqualToString: NSAccessibilityBoundsForRangeParameterizedAttribute]) {
879 NSRange range = [parameter rangeValue];
880 QRect firstRect = iface->textInterface()->characterRect(range.location);
882 if (range.length > 0) {
883 NSUInteger position = range.location + range.length - 1;
884 if (position > range.location && iface->textInterface()->text(position, position + 1) ==
"\n"_L1)
886 QRect lastRect = iface->textInterface()->characterRect(position);
887 rect = firstRect.united(lastRect);
892 return [NSValue valueWithRect:QCocoaScreen::mapToNative(rect)];
894 if ([attribute isEqualToString: NSAccessibilityAttributedStringForRangeParameterizedAttribute]) {
895 NSRange range = [parameter rangeValue];
896 QString text = iface->textInterface()->text(range.location, range.location + range.length);
897 return [[NSAttributedString alloc] initWithString:text.toNSString()];
898 }
else if ([attribute isEqualToString: NSAccessibilityRangeForPositionParameterizedAttribute]) {
899 QPoint point = QCocoaScreen::mapFromNative([parameter pointValue]).toPoint();
900 int offset = iface->textInterface()->offsetAtPoint(point);
901 return [NSValue valueWithRange:NSMakeRange(
static_cast<NSUInteger>(offset), 1)];
902 }
else if ([attribute isEqualToString: NSAccessibilityStyleRangeForIndexParameterizedAttribute]) {
905 iface->textInterface()->attributes([parameter intValue], &start, &end);
906 return [NSValue valueWithRange:NSMakeRange(
static_cast<NSUInteger>(start),
static_cast<NSUInteger>(end - start))];
911- (BOOL)accessibilityIsAttributeSettable:(NSString *)attribute {
912 QAccessibleInterface *iface = self.qtInterface;
916 if ([attribute isEqualToString:NSAccessibilityFocusedAttribute]) {
917 return iface->state().focusable ? YES : NO;
918 }
else if ([attribute isEqualToString:NSAccessibilityValueAttribute]) {
919 if (iface->textInterface() && iface->state().editable)
921 if (iface->valueInterface())
924 }
else if ([attribute isEqualToString:NSAccessibilitySelectedTextRangeAttribute]) {
925 return iface->textInterface() ? YES : NO;
930- (
void)accessibilitySetValue:(id)value forAttribute:(NSString *)attribute {
931 QAccessibleInterface *iface = self.qtInterface;
934 if ([attribute isEqualToString:NSAccessibilityFocusedAttribute]) {
935 if (QAccessibleActionInterface *action = iface->actionInterface())
936 action->doAction(QAccessibleActionInterface::setFocusAction());
937 }
else if ([attribute isEqualToString:NSAccessibilityValueAttribute]) {
938 if (iface->textInterface()) {
939 QString text = QString::fromNSString((NSString *)value);
940 iface->setText(QAccessible::Value, text);
941 }
else if (QAccessibleValueInterface *valueIface = iface->valueInterface()) {
942 double val = [value doubleValue];
943 valueIface->setCurrentValue(val);
945 }
else if ([attribute isEqualToString:NSAccessibilitySelectedTextRangeAttribute]) {
946 if (QAccessibleTextInterface *text = iface->textInterface()) {
947 NSRange range = [value rangeValue];
948 if (range.length > 0)
949 text->setSelection(0, range.location, range.location + range.length);
951 text->setCursorPosition(range.location);
958- (NSArray *)accessibilityActionNames {
959 NSMutableArray *nsActions = [[NSMutableArray
new] autorelease];
960 QAccessibleInterface *iface = self.qtInterface;
964 const QStringList &supportedActionNames = QAccessibleBridgeUtils::effectiveActionNames(iface);
965 for (
const QString &qtAction : supportedActionNames) {
966 NSString *nsAction = QCocoaAccessible::getTranslatedAction(qtAction);
968 [nsActions addObject : nsAction];
974- (NSString *)accessibilityActionDescription:(NSString *)action {
975 QAccessibleInterface *iface = self.qtInterface;
978 QString qtAction = QCocoaAccessible::translateAction(action, iface);
981 if (qtAction.isEmpty()) {
982 if (QAccessibleActionInterface *actionInterface = iface->actionInterface()) {
983 qtAction = QString::fromNSString((NSString *)action);
984 description = actionInterface->localizedActionDescription(qtAction);
987 description = qAccessibleLocalizedActionDescription(qtAction);
989 return description.toNSString();
992- (
void)accessibilityPerformAction:(NSString *)action {
993 if (QAccessibleInterface *iface = self.qtInterface) {
994 const QString qtAction = QCocoaAccessible::translateAction(action, iface);
995 QAccessibleBridgeUtils::performEffectiveAction(iface, qtAction);
1001- (BOOL)accessibilityIsIgnored {
1005 if (self.isManagedByParent)
1008 if (QAccessibleInterface *iface = self.qtInterface)
1009 return QCocoaAccessible::shouldBeIgnored(iface);
1013- (id)accessibilityHitTest:(NSPoint)point {
1014 QAccessibleInterface *iface = self.qtInterface;
1017 return NSAccessibilityUnignoredAncestor(self);
1020 QPointF screenPoint = QCocoaScreen::mapFromNative(point);
1021 QAccessibleInterface *childInterface = iface->childAt(screenPoint.x(), screenPoint.y());
1023 if (!childInterface || !childInterface->isValid())
1024 return NSAccessibilityUnignoredAncestor(self);
1027 QAccessibleInterface *childOfChildInterface =
nullptr;
1029 childOfChildInterface = childInterface->childAt(screenPoint.x(), screenPoint.y());
1030 if (childOfChildInterface && childOfChildInterface->isValid())
1031 childInterface = childOfChildInterface;
1032 }
while (childOfChildInterface && childOfChildInterface->isValid());
1035 QMacAccessibilityElement *accessibleElement = [QMacAccessibilityElement elementWithInterface:childInterface];
1036 if (accessibleElement)
1037 return NSAccessibilityUnignoredAncestor(accessibleElement);
1038 return NSAccessibilityUnignoredAncestor(self);
1041- (id)accessibilityFocusedUIElement {
1042 QAccessibleInterface *iface = self.qtInterface;
1044 qWarning(
"FocusedUIElement for INVALID");
1048 QAccessibleInterface *childInterface = iface->focusChild();
1049 if (childInterface && childInterface->isValid()) {
1050 QMacAccessibilityElement *accessibleElement = [QMacAccessibilityElement elementWithInterface:childInterface];
1051 return NSAccessibilityUnignoredAncestor(accessibleElement);
1054 return NSAccessibilityUnignoredAncestor(self);
1057- (NSString *) accessibilityHelp {
1058 if (QAccessibleInterface *iface = self.qtInterface) {
1059 const QString helpText = iface->text(QAccessible::Help);
1060 if (!helpText.isEmpty())
1061 return helpText.toNSString();
1067
1068
1069- (NSInteger) accessibilityIndex {
1070 NSInteger index = 0;
1071 if (synthesizedRole == NSAccessibilityCellRole)
1072 return m_columnIndex;
1073 if (QAccessibleInterface *iface = self.qtInterface) {
1074 if (self.isManagedByParent) {
1077 if (iface->tableInterface()) {
1078 if (m_rowIndex >= 0)
1079 index = NSInteger(m_rowIndex);
1080 else if (m_columnIndex >= 0)
1081 index = NSInteger(m_columnIndex);
1088- (NSArray *) accessibilityRows {
1089 if (!synthesizedRole && rows) {
1090 QAccessibleInterface *iface = self.qtInterface;
1091 QAccessibleTableInterface *tableInterface = iface ? iface->tableInterface() :
nullptr;
1092 if (tableInterface) {
1093 const unsigned int rowCount = tableInterface->rowCount();
1094 if (rows.count != rowCount) {
1095 qCDebug(lcAccessibilityTable) <<
"Updating table rows with" << rowCount <<
"rows";
1100 rows = [self populateTableArray:NSAccessibilityRowRole
1104 return NSAccessibilityUnignoredChildren(rows);
1110- (NSArray *) accessibilityColumns {
1112 if (!synthesizedRole && columns) {
1113 QAccessibleInterface *iface = self.qtInterface;
1114 if (iface && iface->tableInterface())
1115 return NSAccessibilityUnignoredChildren(columns);
1122- (NSArray *) accessibilityTabs {
1123 QAccessibleInterface *iface = self.qtInterface;
1124 if (iface && iface->role() == QAccessible::PageTabList) {
1125 return QCocoaAccessible::unignoredChildren(iface, [](QAccessibleInterface *child){
1126 return QCocoaAccessible::defaultUnignored(child)
1127 && child->role() == QAccessible::PageTab;