static AccessibilityObject* listObjectForSelection(AtkSelection* selection) { AccessibilityObject* coreSelection = core(selection); // Only list boxes and menu lists supported so far. if (!coreSelection->isListBox() && !coreSelection->isMenuList()) return 0; // For list boxes the list object is just itself. if (coreSelection->isListBox()) return coreSelection; // For menu lists we need to return the first accessible child, // with role MenuListPopupRole, since that's the one holding the list // of items with role MenuListOptionRole. AccessibilityObject::AccessibilityChildrenVector children = coreSelection->children(); if (!children.size()) return 0; AccessibilityObject* listObject = children.at(0).get(); if (!listObject->isMenuListPopup()) return 0; return listObject; }
AccessibilityObject* AXObjectCache::focusedImageMapUIElement(HTMLAreaElement* areaElement) { // Find the corresponding accessibility object for the HTMLAreaElement. This should be // in the list of children for its corresponding image. if (!areaElement) return 0; HTMLImageElement* imageElement = areaElement->imageElement(); if (!imageElement) return 0; AccessibilityObject* axRenderImage = areaElement->document()->axObjectCache()->getOrCreate(imageElement); if (!axRenderImage) return 0; AccessibilityObject::AccessibilityChildrenVector imageChildren = axRenderImage->children(); unsigned count = imageChildren.size(); for (unsigned k = 0; k < count; ++k) { AccessibilityObject* child = imageChildren[k].get(); if (!child->isImageMapLink()) continue; if (static_cast<AccessibilityImageMapLink*>(child)->areaElement() == areaElement) return child; } return 0; }
static gint webkitAccessibleSelectionGetSelectionCount(AtkSelection* selection) { g_return_val_if_fail(ATK_SELECTION(selection), 0); returnValIfWebKitAccessibleIsInvalid(WEBKIT_ACCESSIBLE(selection), 0); AccessibilityObject* coreSelection = core(selection); if (!coreSelection || !coreSelection->isAccessibilityRenderObject()) return 0; if (coreSelection->isListBox()) { AccessibilityObject::AccessibilityChildrenVector selectedItems; coreSelection->selectedChildren(selectedItems); return static_cast<gint>(selectedItems.size()); } if (coreSelection->isMenuList()) { RenderObject* renderer = coreSelection->renderer(); if (!renderer) return 0; int selectedIndex = downcast<HTMLSelectElement>(renderer->node())->selectedIndex(); return selectedIndex >= 0 && selectedIndex < static_cast<int>(downcast<HTMLSelectElement>(renderer->node())->listItems().size()); } return 0; }
static AtkObject* webkitAccessibleRefChild(AtkObject* object, gint index) { if (index < 0) return 0; AccessibilityObject* coreObject = core(object); AccessibilityObject* coreChild = 0; // Tables are special cases because rows should be bypassed, but // still taking their cells into account. if (coreObject->isAccessibilityTable()) coreChild = getChildForTable(coreObject, index); else { AccessibilityObject::AccessibilityChildrenVector children = coreObject->children(); if (static_cast<unsigned>(index) >= children.size()) return 0; coreChild = children.at(index).get(); } if (!coreChild) return 0; AtkObject* child = coreChild->wrapper(); atk_object_set_parent(child, object); g_object_ref(child); return child; }
static gint webkitAccessibleGetIndexInParent(AtkObject* object) { AccessibilityObject* coreObject = core(object); AccessibilityObject* parent = coreObject->parentObjectUnignored(); if (!parent && isRootObject(coreObject)) { AtkObject* atkParent = atkParentOfRootObject(object); if (!atkParent) return -1; unsigned count = atk_object_get_n_accessible_children(atkParent); for (unsigned i = 0; i < count; ++i) { AtkObject* child = atk_object_ref_accessible_child(atkParent, i); bool childIsObject = child == object; g_object_unref(child); if (childIsObject) return i; } } // Need to calculate the index of the cell in the table, as // rows won't be exposed to assistive technologies in GTK. if (parent && parent->isTableRow() && coreObject->isTableCell()) return getIndexInParentForCellInRow(coreObject); AccessibilityObject::AccessibilityChildrenVector children = parent->children(); unsigned count = children.size(); for (unsigned i = 0; i < count; ++i) { if (children[i] == coreObject) return i; } return -1; }
static gint getIndexInParentForCellInRow(AccessibilityObject* coreObject) { AccessibilityObject* parent = coreObject->parentObjectUnignored(); if (!parent) return -1; AccessibilityObject* grandParent = parent->parentObjectUnignored(); if (!grandParent) return -1; AccessibilityObject::AccessibilityChildrenVector rows = grandParent->children(); size_t rowsCount = rows.size(); size_t previousCellsCount = 0; // Look for the actual index of the cell inside the table. for (unsigned i = 0; i < rowsCount; ++i) { if (!rows[i]->isTableRow()) continue; AccessibilityObject::AccessibilityChildrenVector cells = rows[i]->children(); size_t cellsCount = cells.size(); if (rows[i] == parent) { for (unsigned j = 0; j < cellsCount; ++j) { if (cells[j] == coreObject) return previousCellsCount + j; } } previousCellsCount += cellsCount; } return -1; }
static AccessibilityObject* optionFromSelection(AtkSelection* selection, gint index) { // i is the ith selection as opposed to the ith child. AccessibilityObject* coreSelection = core(selection); if (!coreSelection || !coreSelection->isAccessibilityRenderObject() || index < 0) return 0; AccessibilityObject::AccessibilityChildrenVector selectedItems; if (coreSelection->isListBox()) coreSelection->selectedChildren(selectedItems); else if (coreSelection->isMenuList()) { RenderObject* renderer = coreSelection->renderer(); if (!renderer) return 0; HTMLSelectElement* selectNode = toHTMLSelectElement(renderer->node()); int selectedIndex = selectNode->selectedIndex(); const Vector<HTMLElement*> listItems = selectNode->listItems(); if (selectedIndex < 0 || selectedIndex >= static_cast<int>(listItems.size())) return 0; return optionFromList(selection, selectedIndex); } if (index < static_cast<gint>(selectedItems.size())) return selectedItems.at(index).get(); return 0; }
static gint cellIndex(AccessibilityTableCell* axCell, AccessibilityTable* axTable) { // Calculate the cell's index as if we had a traditional Gtk+ table in // which cells are all direct children of the table, arranged row-first. AccessibilityObject::AccessibilityChildrenVector allCells; axTable->cells(allCells); AccessibilityObject::AccessibilityChildrenVector::iterator position; position = std::find(allCells.begin(), allCells.end(), axCell); if (position == allCells.end()) return -1; return position - allCells.begin(); }
static AccessibilityTableCell* cellAtIndex(AtkTable* table, gint index) { AccessibilityObject* accTable = core(table); if (accTable->isAccessibilityRenderObject()) { AccessibilityObject::AccessibilityChildrenVector allCells; toAccessibilityTable(accTable)->cells(allCells); if (0 <= index && static_cast<unsigned>(index) < allCells.size()) { AccessibilityObject* accCell = allCells.at(index).get(); return toAccessibilityTableCell(accCell); } } return 0; }
static gint webkit_accessible_get_index_in_parent(AtkObject* object) { AccessibilityObject* coreObject = core(object); AccessibilityObject* parent = coreObject->parentObjectUnignored(); g_return_val_if_fail(parent, 0); AccessibilityObject::AccessibilityChildrenVector children = parent->children(); unsigned count = children.size(); for (unsigned i = 0; i < count; ++i) { if (children[i] == coreObject) return i; } return 0; }
static gboolean webkitAccessibleSelectionClearSelection(AtkSelection* selection) { AccessibilityObject* coreSelection = core(selection); if (!coreSelection) return FALSE; AccessibilityObject::AccessibilityChildrenVector selectedItems; if (coreSelection->isListBox() || coreSelection->isMenuList()) { // Set the list of selected items to an empty list; then verify that it worked. AccessibilityListBox* listBox = static_cast<AccessibilityListBox*>(coreSelection); listBox->setSelectedChildren(selectedItems); listBox->selectedChildren(selectedItems); return !selectedItems.size(); } return FALSE; }
static AtkObject* webkit_accessible_table_get_row_header(AtkTable* table, gint row) { AccessibilityObject* accTable = core(table); if (accTable->isAccessibilityRenderObject()) { AccessibilityObject::AccessibilityChildrenVector allRowHeaders; static_cast<AccessibilityTable*>(accTable)->rowHeaders(allRowHeaders); unsigned rowCount = allRowHeaders.size(); for (unsigned k = 0; k < rowCount; ++k) { AccessibilityObject* rowObject = allRowHeaders[k]->parentObject(); if (static_cast<AccessibilityTableRow*>(rowObject)->rowIndex() == row) return allRowHeaders[k]->wrapper(); } } return 0; }
static gboolean webkitAccessibleSelectionSelectAllSelection(AtkSelection* selection) { AccessibilityObject* coreSelection = core(selection); if (!coreSelection || !coreSelection->isMultiSelectable()) return FALSE; AccessibilityObject::AccessibilityChildrenVector children = coreSelection->children(); if (coreSelection->isListBox()) { AccessibilityListBox* listBox = static_cast<AccessibilityListBox*>(coreSelection); listBox->setSelectedChildren(children); AccessibilityObject::AccessibilityChildrenVector selectedItems; listBox->selectedChildren(selectedItems); return selectedItems.size() == children.size(); } return FALSE; }
static AtkObject* webkitAccessibleTableGetRowHeader(AtkTable* table, gint row) { AccessibilityObject* accTable = core(table); if (accTable->isAccessibilityRenderObject()) { AccessibilityObject::AccessibilityChildrenVector allRowHeaders; static_cast<AccessibilityTable*>(accTable)->rowHeaders(allRowHeaders); unsigned rowCount = allRowHeaders.size(); for (unsigned k = 0; k < rowCount; ++k) { pair<unsigned, unsigned> rowRange; AccessibilityTableCell* cell = static_cast<AccessibilityTableCell*>(allRowHeaders.at(k).get()); cell->rowIndexRange(rowRange); if (rowRange.first <= static_cast<unsigned>(row) && static_cast<unsigned>(row) < rowRange.first + rowRange.second) return allRowHeaders[k]->wrapper(); } } return 0; }
static AccessibilityObject* optionFromList(AtkSelection* selection, gint index) { AccessibilityObject* coreSelection = core(selection); if (!coreSelection || index < 0) return 0; // Need to select the proper list object depending on the type. AccessibilityObject* listObject = listObjectForSelection(selection); if (!listObject) return 0; AccessibilityObject::AccessibilityChildrenVector options = listObject->children(); if (index < static_cast<gint>(options.size())) return options.at(index).get(); return 0; }
static gint getNChildrenForTable(AccessibilityObject* coreObject) { AccessibilityObject::AccessibilityChildrenVector tableChildren = coreObject->children(); size_t tableChildrenCount = tableChildren.size(); size_t cellsCount = 0; // Look for the actual index of the cell inside the table. for (unsigned i = 0; i < tableChildrenCount; ++i) { if (tableChildren[i]->isTableRow()) { AccessibilityObject::AccessibilityChildrenVector rowChildren = tableChildren[i]->children(); cellsCount += rowChildren.size(); } else cellsCount++; } return cellsCount; }
void AccessibilityTable::cells(AccessibilityObject::AccessibilityChildrenVector& cells) { if (!m_renderer) return; updateChildrenIfNecessary(); for (const auto& row : m_rows) cells.appendVector(row->children()); }
static gboolean webkitAccessibleSelectionClearSelection(AtkSelection* selection) { g_return_val_if_fail(ATK_SELECTION(selection), FALSE); returnValIfWebKitAccessibleIsInvalid(WEBKIT_ACCESSIBLE(selection), FALSE); AccessibilityObject* coreSelection = core(selection); if (!coreSelection) return FALSE; AccessibilityObject::AccessibilityChildrenVector selectedItems; if (coreSelection->isListBox() || coreSelection->isMenuList()) { // Set the list of selected items to an empty list; then verify that it worked. AccessibilityListBox* listBox = toAccessibilityListBox(coreSelection); listBox->setSelectedChildren(selectedItems); listBox->selectedChildren(selectedItems); return !selectedItems.size(); } return FALSE; }
void AccessibilityTable::cells(AccessibilityObject::AccessibilityChildrenVector& cells) { if (!m_renderer) return; updateChildrenIfNecessary(); for (size_t row = 0; row < m_rows.size(); ++row) cells.appendVector(m_rows[row]->children()); }
static gboolean webkitAccessibleSelectionSelectAllSelection(AtkSelection* selection) { g_return_val_if_fail(ATK_SELECTION(selection), FALSE); returnValIfWebKitAccessibleIsInvalid(WEBKIT_ACCESSIBLE(selection), FALSE); AccessibilityObject* coreSelection = core(selection); if (!coreSelection || !coreSelection->isMultiSelectable()) return FALSE; if (coreSelection->isListBox()) { const AccessibilityObject::AccessibilityChildrenVector& children = coreSelection->children(); AccessibilityListBox* listBox = toAccessibilityListBox(coreSelection); listBox->setSelectedChildren(children); AccessibilityObject::AccessibilityChildrenVector selectedItems; listBox->selectedChildren(selectedItems); return selectedItems.size() == children.size(); } return FALSE; }
static AtkObject* webkitAccessibleTableGetRowHeader(AtkTable* table, gint row) { g_return_val_if_fail(ATK_TABLE(table), 0); returnValIfWebKitAccessibleIsInvalid(WEBKIT_ACCESSIBLE(table), 0); AccessibilityObject* accTable = core(table); if (accTable->isAccessibilityRenderObject()) { AccessibilityObject::AccessibilityChildrenVector allRowHeaders; toAccessibilityTable(accTable)->rowHeaders(allRowHeaders); unsigned rowCount = allRowHeaders.size(); for (unsigned k = 0; k < rowCount; ++k) { pair<unsigned, unsigned> rowRange; AccessibilityTableCell* cell = toAccessibilityTableCell(allRowHeaders.at(k).get()); cell->rowIndexRange(rowRange); if (rowRange.first <= static_cast<unsigned>(row) && static_cast<unsigned>(row) < rowRange.first + rowRange.second) return allRowHeaders[k]->wrapper(); } } return 0; }
void AccessibilityTable::cells(AccessibilityObject::AccessibilityChildrenVector& cells) { if (!m_renderer) return; updateChildrenIfNecessary(); int numRows = m_rows.size(); for (int row = 0; row < numRows; ++row) { AccessibilityChildrenVector rowChildren = m_rows[row]->children(); cells.append(rowChildren); } }
static gint webkitAccessibleSelectionGetSelectionCount(AtkSelection* selection) { AccessibilityObject* coreSelection = core(selection); if (!coreSelection || !coreSelection->isAccessibilityRenderObject()) return 0; if (coreSelection->isListBox()) { AccessibilityObject::AccessibilityChildrenVector selectedItems; coreSelection->selectedChildren(selectedItems); return static_cast<gint>(selectedItems.size()); } if (coreSelection->isMenuList()) { RenderObject* renderer = coreSelection->renderer(); if (!renderer) return 0; int selectedIndex = toHTMLSelectElement(renderer->node())->selectedIndex(); return selectedIndex >= 0 && selectedIndex < static_cast<int>(toHTMLSelectElement(renderer->node())->listItems().size()); } return 0; }
static bool childrenContainOnlyStaticText(const AccessibilityObject::AccessibilityChildrenVector& children) { if (!children.size()) return false; for (const auto& child : children) { if (child->roleValue() == AccessibilityRole::StaticText) continue; if (child->roleValue() == AccessibilityRole::Group) { if (!childrenContainOnlyStaticText(child->children())) return false; } else return false; } return true; }
static AccessibilityObject* getChildForTable(AccessibilityObject* coreObject, gint index) { AccessibilityObject::AccessibilityChildrenVector tableChildren = coreObject->children(); size_t tableChildrenCount = tableChildren.size(); size_t cellsCount = 0; // Look for the actual index of the cell inside the table. size_t current = static_cast<size_t>(index); for (unsigned i = 0; i < tableChildrenCount; ++i) { if (tableChildren[i]->isTableRow()) { AccessibilityObject::AccessibilityChildrenVector rowChildren = tableChildren[i]->children(); size_t rowChildrenCount = rowChildren.size(); if (current < cellsCount + rowChildrenCount) return rowChildren.at(current - cellsCount).get(); cellsCount += rowChildrenCount; } else if (cellsCount == current) return tableChildren[i].get(); else cellsCount++; } // Shouldn't reach if the child was found. return 0; }
static bool childrenContainUnrelatedControls(const AccessibilityObject::AccessibilityChildrenVector& children, AccessibilityObject* controlForLabel) { if (!children.size()) return false; for (const auto& child : children) { if (child->isControl()) { if (child == controlForLabel) continue; return true; } if (childrenContainUnrelatedControls(child->children(), controlForLabel)) return true; } return false; }
static guint16 getInterfaceMaskFromObject(AccessibilityObject* coreObject) { guint16 interfaceMask = 0; // Component interface is always supported interfaceMask |= 1 << WAI_COMPONENT; AccessibilityRole role = coreObject->roleValue(); // Action // As the implementation of the AtkAction interface is a very // basic one (just relays in executing the default action for each // object, and only supports having one action per object), it is // better just to implement this interface for every instance of // the WebKitAccessible class and let WebCore decide what to do. interfaceMask |= 1 << WAI_ACTION; // Selection if (coreObject->isListBox() || coreObject->isMenuList()) interfaceMask |= 1 << WAI_SELECTION; // Get renderer if available. RenderObject* renderer = 0; if (coreObject->isAccessibilityRenderObject()) renderer = coreObject->renderer(); // Hyperlink (links and embedded objects). if (coreObject->isLink() || (renderer && renderer->isReplaced())) interfaceMask |= 1 << WAI_HYPERLINK; // Text & Editable Text if (role == StaticTextRole || coreObject->isMenuListOption()) interfaceMask |= 1 << WAI_TEXT; else { if (coreObject->isTextControl()) { interfaceMask |= 1 << WAI_TEXT; if (!coreObject->isReadOnly()) interfaceMask |= 1 << WAI_EDITABLE_TEXT; } else { if (role != TableRole) { interfaceMask |= 1 << WAI_HYPERTEXT; if ((renderer && renderer->childrenInline()) || roleIsTextType(role)) interfaceMask |= 1 << WAI_TEXT; } // Add the TEXT interface for list items whose // first accessible child has a text renderer if (role == ListItemRole) { AccessibilityObject::AccessibilityChildrenVector children = coreObject->children(); if (children.size()) { AccessibilityObject* axRenderChild = children.at(0).get(); interfaceMask |= getInterfaceMaskFromObject(axRenderChild); } } } } // Image if (coreObject->isImage()) interfaceMask |= 1 << WAI_IMAGE; // Table if (role == TableRole) interfaceMask |= 1 << WAI_TABLE; // Document if (role == WebAreaRole) interfaceMask |= 1 << WAI_DOCUMENT; // Value if (role == SliderRole || role == SpinButtonRole || role == ScrollBarRole || role == ProgressIndicatorRole) interfaceMask |= 1 << WAI_VALUE; #if ENABLE(INPUT_TYPE_COLOR) // Color type. if (role == ColorWellRole) interfaceMask |= 1 << WAI_TEXT; #endif return interfaceMask; }