diff options
Diffstat (limited to 'Source/WebCore/accessibility/AccessibilityARIAGridCell.cpp')
-rw-r--r-- | Source/WebCore/accessibility/AccessibilityARIAGridCell.cpp | 101 |
1 files changed, 72 insertions, 29 deletions
diff --git a/Source/WebCore/accessibility/AccessibilityARIAGridCell.cpp b/Source/WebCore/accessibility/AccessibilityARIAGridCell.cpp index 506e7f25e..36aac823d 100644 --- a/Source/WebCore/accessibility/AccessibilityARIAGridCell.cpp +++ b/Source/WebCore/accessibility/AccessibilityARIAGridCell.cpp @@ -10,7 +10,7 @@ * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of + * 3. Neither the name of Apple Inc. ("Apple") nor the names of * its contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * @@ -32,9 +32,12 @@ #include "AccessibilityObject.h" #include "AccessibilityTable.h" #include "AccessibilityTableRow.h" +#include "HTMLNames.h" namespace WebCore { +using namespace HTMLNames; + AccessibilityARIAGridCell::AccessibilityARIAGridCell(RenderObject* renderer) : AccessibilityTableCell(renderer) { @@ -44,43 +47,37 @@ AccessibilityARIAGridCell::~AccessibilityARIAGridCell() { } -PassRefPtr<AccessibilityARIAGridCell> AccessibilityARIAGridCell::create(RenderObject* renderer) +Ref<AccessibilityARIAGridCell> AccessibilityARIAGridCell::create(RenderObject* renderer) { - return adoptRef(new AccessibilityARIAGridCell(renderer)); + return adoptRef(*new AccessibilityARIAGridCell(renderer)); } AccessibilityTable* AccessibilityARIAGridCell::parentTable() const { - AccessibilityObject* parent = parentObjectUnignored(); - if (!parent) - return nullptr; - - if (parent->isAccessibilityTable()) - return toAccessibilityTable(parent); - - // It could happen that we hadn't reached the parent table yet (in - // case objects for rows were not ignoring accessibility) so for - // that reason we need to run parentObjectUnignored once again. - parent = parent->parentObjectUnignored(); - if (!parent || !parent->isAccessibilityTable()) - return nullptr; - - return toAccessibilityTable(parent); + // ARIA gridcells may have multiple levels of unignored ancestors that are not the parent table, + // including rows and interactive rowgroups. In addition, poorly-formed grids may contain elements + // which pass the tests for inclusion. + for (AccessibilityObject* parent = parentObjectUnignored(); parent; parent = parent->parentObjectUnignored()) { + if (is<AccessibilityTable>(*parent) && downcast<AccessibilityTable>(*parent).isExposableThroughAccessibility()) + return downcast<AccessibilityTable>(parent); + } + + return nullptr; } -void AccessibilityARIAGridCell::rowIndexRange(std::pair<unsigned, unsigned>& rowRange) +void AccessibilityARIAGridCell::rowIndexRange(std::pair<unsigned, unsigned>& rowRange) const { AccessibilityObject* parent = parentObjectUnignored(); if (!parent) return; - if (parent->isTableRow()) { + if (is<AccessibilityTableRow>(*parent)) { // We already got a table row, use its API. - rowRange.first = toAccessibilityTableRow(parent)->rowIndex(); - } else if (parent->isAccessibilityTable()) { + rowRange.first = downcast<AccessibilityTableRow>(*parent).rowIndex(); + } else if (is<AccessibilityTable>(*parent) && downcast<AccessibilityTable>(*parent).isExposableThroughAccessibility()) { // We reached the parent table, so we need to inspect its // children to determine the row index for the cell in it. - unsigned columnCount = toAccessibilityTable(parent)->columnCount(); + unsigned columnCount = downcast<AccessibilityTable>(*parent).columnCount(); if (!columnCount) return; @@ -94,17 +91,51 @@ void AccessibilityARIAGridCell::rowIndexRange(std::pair<unsigned, unsigned>& row } } - // as far as I can tell, grid cells cannot span rows - rowRange.second = 1; + // ARIA 1.1, aria-rowspan attribute is intended for cells and gridcells which are not contained in a native table. + // So we should check for that attribute here. + rowRange.second = ariaRowSpanWithRowIndex(rowRange.first); +} + +unsigned AccessibilityARIAGridCell::ariaRowSpanWithRowIndex(unsigned rowIndex) const +{ + unsigned rowSpan = AccessibilityTableCell::ariaRowSpan(); + AccessibilityObject* parent = parentObjectUnignored(); + if (!parent) + return 1; + + // Setting the value to 0 indicates that the cell or gridcell is to span all the remaining rows in the row group. + if (!rowSpan) { + // rowSpan defaults to 1. + rowSpan = 1; + if (AccessibilityObject* parentRowGroup = this->parentRowGroup()) { + // If the row group is the parent table, we use total row count to calculate the span. + if (is<AccessibilityTable>(*parentRowGroup)) + rowSpan = downcast<AccessibilityTable>(*parentRowGroup).rowCount() - rowIndex; + // Otherwise, we have to get the index for the current row within the parent row group. + else if (is<AccessibilityTableRow>(*parent)) { + const auto& siblings = parentRowGroup->children(); + unsigned rowCount = siblings.size(); + for (unsigned k = 0; k < rowCount; ++k) { + if (siblings[k].get() == parent) { + rowSpan = rowCount - k; + break; + } + } + } + } + } + + return rowSpan; } -void AccessibilityARIAGridCell::columnIndexRange(std::pair<unsigned, unsigned>& columnRange) +void AccessibilityARIAGridCell::columnIndexRange(std::pair<unsigned, unsigned>& columnRange) const { AccessibilityObject* parent = parentObjectUnignored(); if (!parent) return; - if (!parent->isTableRow() && !parent->isAccessibilityTable()) + if (!is<AccessibilityTableRow>(*parent) + && !(is<AccessibilityTable>(*parent) && downcast<AccessibilityTable>(*parent).isExposableThroughAccessibility())) return; const AccessibilityChildrenVector& siblings = parent->children(); @@ -116,8 +147,20 @@ void AccessibilityARIAGridCell::columnIndexRange(std::pair<unsigned, unsigned>& } } - // as far as I can tell, grid cells cannot span columns - columnRange.second = 1; + // ARIA 1.1, aria-colspan attribute is intended for cells and gridcells which are not contained in a native table. + // So we should check for that attribute here. + columnRange.second = ariaColumnSpan(); +} + +AccessibilityObject* AccessibilityARIAGridCell::parentRowGroup() const +{ + for (AccessibilityObject* parent = parentObject(); parent; parent = parent->parentObject()) { + if (parent->hasTagName(theadTag) || parent->hasTagName(tbodyTag) || parent->hasTagName(tfootTag) || parent->roleValue() == RowGroupRole) + return parent; + } + + // If there's no row group found, we use the parent table as the row group. + return parentTable(); } } // namespace WebCore |