mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-26 06:11:37 +00:00
b999f08200
Previously, we would always calculate the name for tr elements from their descendants unconditionally. Assistive technologies aren't using this information, moreover, it causes problems if the name gets too long, for example in layout tables. We now only calculate the name if the tr element has an explicit ARIA role. Differential Revision: https://phabricator.services.mozilla.com/D39314 --HG-- extra : moz-landing-system : lando
612 lines
18 KiB
C++
612 lines
18 KiB
C++
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
|
/* This Source Code Form is subject to the terms of the Mozilla Public
|
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
|
|
|
#include "ARIAGridAccessible-inl.h"
|
|
|
|
#include "Accessible-inl.h"
|
|
#include "AccIterator.h"
|
|
#include "nsAccUtils.h"
|
|
#include "Role.h"
|
|
#include "States.h"
|
|
|
|
#include "nsIMutableArray.h"
|
|
#include "nsIPersistentProperties2.h"
|
|
#include "nsComponentManagerUtils.h"
|
|
|
|
using namespace mozilla;
|
|
using namespace mozilla::a11y;
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
// ARIAGridAccessible
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
// Constructor
|
|
|
|
ARIAGridAccessible::ARIAGridAccessible(nsIContent* aContent,
|
|
DocAccessible* aDoc)
|
|
: HyperTextAccessibleWrap(aContent, aDoc) {
|
|
mGenericTypes |= eTable;
|
|
}
|
|
|
|
role ARIAGridAccessible::NativeRole() const {
|
|
a11y::role r = GetAccService()->MarkupRole(mContent);
|
|
return r != roles::NOTHING ? r : roles::TABLE;
|
|
}
|
|
|
|
already_AddRefed<nsIPersistentProperties>
|
|
ARIAGridAccessible::NativeAttributes() {
|
|
nsCOMPtr<nsIPersistentProperties> attributes =
|
|
AccessibleWrap::NativeAttributes();
|
|
|
|
if (IsProbablyLayoutTable()) {
|
|
nsAutoString unused;
|
|
attributes->SetStringProperty(NS_LITERAL_CSTRING("layout-guess"),
|
|
NS_LITERAL_STRING("true"), unused);
|
|
}
|
|
|
|
return attributes.forget();
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
// Table
|
|
|
|
uint32_t ARIAGridAccessible::ColCount() const {
|
|
AccIterator rowIter(this, filters::GetRow);
|
|
Accessible* row = rowIter.Next();
|
|
if (!row) return 0;
|
|
|
|
AccIterator cellIter(row, filters::GetCell);
|
|
Accessible* cell = nullptr;
|
|
|
|
uint32_t colCount = 0;
|
|
while ((cell = cellIter.Next())) {
|
|
MOZ_ASSERT(cell->IsTableCell(), "No table or grid cell!");
|
|
colCount += cell->AsTableCell()->ColExtent();
|
|
}
|
|
|
|
return colCount;
|
|
}
|
|
|
|
uint32_t ARIAGridAccessible::RowCount() {
|
|
uint32_t rowCount = 0;
|
|
AccIterator rowIter(this, filters::GetRow);
|
|
while (rowIter.Next()) rowCount++;
|
|
|
|
return rowCount;
|
|
}
|
|
|
|
Accessible* ARIAGridAccessible::CellAt(uint32_t aRowIndex,
|
|
uint32_t aColumnIndex) {
|
|
Accessible* row = RowAt(aRowIndex);
|
|
if (!row) return nullptr;
|
|
|
|
return CellInRowAt(row, aColumnIndex);
|
|
}
|
|
|
|
bool ARIAGridAccessible::IsColSelected(uint32_t aColIdx) {
|
|
if (IsARIARole(nsGkAtoms::table)) return false;
|
|
|
|
AccIterator rowIter(this, filters::GetRow);
|
|
Accessible* row = rowIter.Next();
|
|
if (!row) return false;
|
|
|
|
do {
|
|
if (!nsAccUtils::IsARIASelected(row)) {
|
|
Accessible* cell = CellInRowAt(row, aColIdx);
|
|
if (!cell || !nsAccUtils::IsARIASelected(cell)) return false;
|
|
}
|
|
} while ((row = rowIter.Next()));
|
|
|
|
return true;
|
|
}
|
|
|
|
bool ARIAGridAccessible::IsRowSelected(uint32_t aRowIdx) {
|
|
if (IsARIARole(nsGkAtoms::table)) return false;
|
|
|
|
Accessible* row = RowAt(aRowIdx);
|
|
if (!row) return false;
|
|
|
|
if (!nsAccUtils::IsARIASelected(row)) {
|
|
AccIterator cellIter(row, filters::GetCell);
|
|
Accessible* cell = nullptr;
|
|
while ((cell = cellIter.Next())) {
|
|
if (!nsAccUtils::IsARIASelected(cell)) return false;
|
|
}
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
bool ARIAGridAccessible::IsCellSelected(uint32_t aRowIdx, uint32_t aColIdx) {
|
|
if (IsARIARole(nsGkAtoms::table)) return false;
|
|
|
|
Accessible* row = RowAt(aRowIdx);
|
|
if (!row) return false;
|
|
|
|
if (!nsAccUtils::IsARIASelected(row)) {
|
|
Accessible* cell = CellInRowAt(row, aColIdx);
|
|
if (!cell || !nsAccUtils::IsARIASelected(cell)) return false;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
uint32_t ARIAGridAccessible::SelectedCellCount() {
|
|
if (IsARIARole(nsGkAtoms::table)) return 0;
|
|
|
|
uint32_t count = 0, colCount = ColCount();
|
|
|
|
AccIterator rowIter(this, filters::GetRow);
|
|
Accessible* row = nullptr;
|
|
|
|
while ((row = rowIter.Next())) {
|
|
if (nsAccUtils::IsARIASelected(row)) {
|
|
count += colCount;
|
|
continue;
|
|
}
|
|
|
|
AccIterator cellIter(row, filters::GetCell);
|
|
Accessible* cell = nullptr;
|
|
|
|
while ((cell = cellIter.Next())) {
|
|
if (nsAccUtils::IsARIASelected(cell)) count++;
|
|
}
|
|
}
|
|
|
|
return count;
|
|
}
|
|
|
|
uint32_t ARIAGridAccessible::SelectedColCount() {
|
|
if (IsARIARole(nsGkAtoms::table)) return 0;
|
|
|
|
uint32_t colCount = ColCount();
|
|
if (!colCount) return 0;
|
|
|
|
AccIterator rowIter(this, filters::GetRow);
|
|
Accessible* row = rowIter.Next();
|
|
if (!row) return 0;
|
|
|
|
nsTArray<bool> isColSelArray(colCount);
|
|
isColSelArray.AppendElements(colCount);
|
|
memset(isColSelArray.Elements(), true, colCount * sizeof(bool));
|
|
|
|
uint32_t selColCount = colCount;
|
|
do {
|
|
if (nsAccUtils::IsARIASelected(row)) continue;
|
|
|
|
AccIterator cellIter(row, filters::GetCell);
|
|
Accessible* cell = nullptr;
|
|
for (uint32_t colIdx = 0; (cell = cellIter.Next()) && colIdx < colCount;
|
|
colIdx++)
|
|
if (isColSelArray[colIdx] && !nsAccUtils::IsARIASelected(cell)) {
|
|
isColSelArray[colIdx] = false;
|
|
selColCount--;
|
|
}
|
|
} while ((row = rowIter.Next()));
|
|
|
|
return selColCount;
|
|
}
|
|
|
|
uint32_t ARIAGridAccessible::SelectedRowCount() {
|
|
if (IsARIARole(nsGkAtoms::table)) return 0;
|
|
|
|
uint32_t count = 0;
|
|
|
|
AccIterator rowIter(this, filters::GetRow);
|
|
Accessible* row = nullptr;
|
|
|
|
while ((row = rowIter.Next())) {
|
|
if (nsAccUtils::IsARIASelected(row)) {
|
|
count++;
|
|
continue;
|
|
}
|
|
|
|
AccIterator cellIter(row, filters::GetCell);
|
|
Accessible* cell = cellIter.Next();
|
|
if (!cell) continue;
|
|
|
|
bool isRowSelected = true;
|
|
do {
|
|
if (!nsAccUtils::IsARIASelected(cell)) {
|
|
isRowSelected = false;
|
|
break;
|
|
}
|
|
} while ((cell = cellIter.Next()));
|
|
|
|
if (isRowSelected) count++;
|
|
}
|
|
|
|
return count;
|
|
}
|
|
|
|
void ARIAGridAccessible::SelectedCells(nsTArray<Accessible*>* aCells) {
|
|
if (IsARIARole(nsGkAtoms::table)) return;
|
|
|
|
AccIterator rowIter(this, filters::GetRow);
|
|
|
|
Accessible* row = nullptr;
|
|
while ((row = rowIter.Next())) {
|
|
AccIterator cellIter(row, filters::GetCell);
|
|
Accessible* cell = nullptr;
|
|
|
|
if (nsAccUtils::IsARIASelected(row)) {
|
|
while ((cell = cellIter.Next())) aCells->AppendElement(cell);
|
|
|
|
continue;
|
|
}
|
|
|
|
while ((cell = cellIter.Next())) {
|
|
if (nsAccUtils::IsARIASelected(cell)) aCells->AppendElement(cell);
|
|
}
|
|
}
|
|
}
|
|
|
|
void ARIAGridAccessible::SelectedCellIndices(nsTArray<uint32_t>* aCells) {
|
|
if (IsARIARole(nsGkAtoms::table)) return;
|
|
|
|
uint32_t colCount = ColCount();
|
|
|
|
AccIterator rowIter(this, filters::GetRow);
|
|
Accessible* row = nullptr;
|
|
for (uint32_t rowIdx = 0; (row = rowIter.Next()); rowIdx++) {
|
|
if (nsAccUtils::IsARIASelected(row)) {
|
|
for (uint32_t colIdx = 0; colIdx < colCount; colIdx++)
|
|
aCells->AppendElement(rowIdx * colCount + colIdx);
|
|
|
|
continue;
|
|
}
|
|
|
|
AccIterator cellIter(row, filters::GetCell);
|
|
Accessible* cell = nullptr;
|
|
for (uint32_t colIdx = 0; (cell = cellIter.Next()); colIdx++) {
|
|
if (nsAccUtils::IsARIASelected(cell))
|
|
aCells->AppendElement(rowIdx * colCount + colIdx);
|
|
}
|
|
}
|
|
}
|
|
|
|
void ARIAGridAccessible::SelectedColIndices(nsTArray<uint32_t>* aCols) {
|
|
if (IsARIARole(nsGkAtoms::table)) return;
|
|
|
|
uint32_t colCount = ColCount();
|
|
if (!colCount) return;
|
|
|
|
AccIterator rowIter(this, filters::GetRow);
|
|
Accessible* row = rowIter.Next();
|
|
if (!row) return;
|
|
|
|
nsTArray<bool> isColSelArray(colCount);
|
|
isColSelArray.AppendElements(colCount);
|
|
memset(isColSelArray.Elements(), true, colCount * sizeof(bool));
|
|
|
|
do {
|
|
if (nsAccUtils::IsARIASelected(row)) continue;
|
|
|
|
AccIterator cellIter(row, filters::GetCell);
|
|
Accessible* cell = nullptr;
|
|
for (uint32_t colIdx = 0; (cell = cellIter.Next()) && colIdx < colCount;
|
|
colIdx++)
|
|
if (isColSelArray[colIdx] && !nsAccUtils::IsARIASelected(cell)) {
|
|
isColSelArray[colIdx] = false;
|
|
}
|
|
} while ((row = rowIter.Next()));
|
|
|
|
for (uint32_t colIdx = 0; colIdx < colCount; colIdx++)
|
|
if (isColSelArray[colIdx]) aCols->AppendElement(colIdx);
|
|
}
|
|
|
|
void ARIAGridAccessible::SelectedRowIndices(nsTArray<uint32_t>* aRows) {
|
|
if (IsARIARole(nsGkAtoms::table)) return;
|
|
|
|
AccIterator rowIter(this, filters::GetRow);
|
|
Accessible* row = nullptr;
|
|
for (uint32_t rowIdx = 0; (row = rowIter.Next()); rowIdx++) {
|
|
if (nsAccUtils::IsARIASelected(row)) {
|
|
aRows->AppendElement(rowIdx);
|
|
continue;
|
|
}
|
|
|
|
AccIterator cellIter(row, filters::GetCell);
|
|
Accessible* cell = cellIter.Next();
|
|
if (!cell) continue;
|
|
|
|
bool isRowSelected = true;
|
|
do {
|
|
if (!nsAccUtils::IsARIASelected(cell)) {
|
|
isRowSelected = false;
|
|
break;
|
|
}
|
|
} while ((cell = cellIter.Next()));
|
|
|
|
if (isRowSelected) aRows->AppendElement(rowIdx);
|
|
}
|
|
}
|
|
|
|
void ARIAGridAccessible::SelectRow(uint32_t aRowIdx) {
|
|
if (IsARIARole(nsGkAtoms::table)) return;
|
|
|
|
AccIterator rowIter(this, filters::GetRow);
|
|
|
|
Accessible* row = nullptr;
|
|
for (uint32_t rowIdx = 0; (row = rowIter.Next()); rowIdx++) {
|
|
DebugOnly<nsresult> rv = SetARIASelected(row, rowIdx == aRowIdx);
|
|
NS_ASSERTION(NS_SUCCEEDED(rv), "SetARIASelected() Shouldn't fail!");
|
|
}
|
|
}
|
|
|
|
void ARIAGridAccessible::SelectCol(uint32_t aColIdx) {
|
|
if (IsARIARole(nsGkAtoms::table)) return;
|
|
|
|
AccIterator rowIter(this, filters::GetRow);
|
|
|
|
Accessible* row = nullptr;
|
|
while ((row = rowIter.Next())) {
|
|
// Unselect all cells in the row.
|
|
DebugOnly<nsresult> rv = SetARIASelected(row, false);
|
|
NS_ASSERTION(NS_SUCCEEDED(rv), "SetARIASelected() Shouldn't fail!");
|
|
|
|
// Select cell at the column index.
|
|
Accessible* cell = CellInRowAt(row, aColIdx);
|
|
if (cell) SetARIASelected(cell, true);
|
|
}
|
|
}
|
|
|
|
void ARIAGridAccessible::UnselectRow(uint32_t aRowIdx) {
|
|
if (IsARIARole(nsGkAtoms::table)) return;
|
|
|
|
Accessible* row = RowAt(aRowIdx);
|
|
if (row) SetARIASelected(row, false);
|
|
}
|
|
|
|
void ARIAGridAccessible::UnselectCol(uint32_t aColIdx) {
|
|
if (IsARIARole(nsGkAtoms::table)) return;
|
|
|
|
AccIterator rowIter(this, filters::GetRow);
|
|
|
|
Accessible* row = nullptr;
|
|
while ((row = rowIter.Next())) {
|
|
Accessible* cell = CellInRowAt(row, aColIdx);
|
|
if (cell) SetARIASelected(cell, false);
|
|
}
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
// Protected
|
|
|
|
nsresult ARIAGridAccessible::SetARIASelected(Accessible* aAccessible,
|
|
bool aIsSelected, bool aNotify) {
|
|
if (IsARIARole(nsGkAtoms::table)) return NS_OK;
|
|
|
|
nsIContent* content = aAccessible->GetContent();
|
|
NS_ENSURE_STATE(content);
|
|
|
|
nsresult rv = NS_OK;
|
|
if (content->IsElement()) {
|
|
if (aIsSelected)
|
|
rv = content->AsElement()->SetAttr(kNameSpaceID_None,
|
|
nsGkAtoms::aria_selected,
|
|
NS_LITERAL_STRING("true"), aNotify);
|
|
else
|
|
rv = content->AsElement()->SetAttr(kNameSpaceID_None,
|
|
nsGkAtoms::aria_selected,
|
|
NS_LITERAL_STRING("false"), aNotify);
|
|
}
|
|
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
// No "smart" select/unselect for internal call.
|
|
if (!aNotify) return NS_OK;
|
|
|
|
// If row or cell accessible was selected then we're able to not bother about
|
|
// selection of its cells or its row because our algorithm is row oriented,
|
|
// i.e. we check selection on row firstly and then on cells.
|
|
if (aIsSelected) return NS_OK;
|
|
|
|
roles::Role role = aAccessible->Role();
|
|
|
|
// If the given accessible is row that was unselected then remove
|
|
// aria-selected from cell accessible.
|
|
if (role == roles::ROW) {
|
|
AccIterator cellIter(aAccessible, filters::GetCell);
|
|
Accessible* cell = nullptr;
|
|
|
|
while ((cell = cellIter.Next())) {
|
|
rv = SetARIASelected(cell, false, false);
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
}
|
|
return NS_OK;
|
|
}
|
|
|
|
// If the given accessible is cell that was unselected and its row is selected
|
|
// then remove aria-selected from row and put aria-selected on
|
|
// siblings cells.
|
|
if (role == roles::GRID_CELL || role == roles::ROWHEADER ||
|
|
role == roles::COLUMNHEADER) {
|
|
Accessible* row = aAccessible->Parent();
|
|
|
|
if (row && row->Role() == roles::ROW && nsAccUtils::IsARIASelected(row)) {
|
|
rv = SetARIASelected(row, false, false);
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
AccIterator cellIter(row, filters::GetCell);
|
|
Accessible* cell = nullptr;
|
|
while ((cell = cellIter.Next())) {
|
|
if (cell != aAccessible) {
|
|
rv = SetARIASelected(cell, true, false);
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return NS_OK;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
// ARIARowAccessible
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
ARIARowAccessible::ARIARowAccessible(nsIContent* aContent, DocAccessible* aDoc)
|
|
: HyperTextAccessibleWrap(aContent, aDoc) {
|
|
mGenericTypes |= eTableRow;
|
|
}
|
|
|
|
role ARIARowAccessible::NativeRole() const {
|
|
a11y::role r = GetAccService()->MarkupRole(mContent);
|
|
return r != roles::NOTHING ? r : roles::ROW;
|
|
}
|
|
|
|
GroupPos ARIARowAccessible::GroupPosition() {
|
|
int32_t count = 0, index = 0;
|
|
Accessible* table = nsAccUtils::TableFor(this);
|
|
if (table &&
|
|
nsCoreUtils::GetUIntAttr(table->GetContent(), nsGkAtoms::aria_rowcount,
|
|
&count) &&
|
|
nsCoreUtils::GetUIntAttr(mContent, nsGkAtoms::aria_rowindex, &index)) {
|
|
return GroupPos(0, index, count);
|
|
}
|
|
|
|
return AccessibleWrap::GroupPosition();
|
|
}
|
|
|
|
// Accessible protected
|
|
ENameValueFlag ARIARowAccessible::NativeName(nsString& aName) const {
|
|
// We want to calculate the name from content only if an ARIA role is
|
|
// present. ARIARowAccessible might also be used by tables with
|
|
// display:block; styling, in which case we do not want the name from
|
|
// content.
|
|
if (HasStrongARIARole()) {
|
|
return AccessibleWrap::NativeName(aName);
|
|
}
|
|
|
|
return eNameOK;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
// ARIAGridCellAccessible
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
// Constructor
|
|
|
|
ARIAGridCellAccessible::ARIAGridCellAccessible(nsIContent* aContent,
|
|
DocAccessible* aDoc)
|
|
: HyperTextAccessibleWrap(aContent, aDoc) {
|
|
mGenericTypes |= eTableCell;
|
|
}
|
|
|
|
role ARIAGridCellAccessible::NativeRole() const {
|
|
a11y::role r = GetAccService()->MarkupRole(mContent);
|
|
return r != roles::NOTHING ? r : roles::CELL;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
// TableCell
|
|
|
|
TableAccessible* ARIAGridCellAccessible::Table() const {
|
|
Accessible* table = nsAccUtils::TableFor(Row());
|
|
return table ? table->AsTable() : nullptr;
|
|
}
|
|
|
|
uint32_t ARIAGridCellAccessible::ColIdx() const {
|
|
Accessible* row = Row();
|
|
if (!row) return 0;
|
|
|
|
int32_t indexInRow = IndexInParent();
|
|
uint32_t colIdx = 0;
|
|
for (int32_t idx = 0; idx < indexInRow; idx++) {
|
|
Accessible* cell = row->GetChildAt(idx);
|
|
if (cell->IsTableCell()) {
|
|
colIdx += cell->AsTableCell()->ColExtent();
|
|
}
|
|
}
|
|
|
|
return colIdx;
|
|
}
|
|
|
|
uint32_t ARIAGridCellAccessible::RowIdx() const { return RowIndexFor(Row()); }
|
|
|
|
bool ARIAGridCellAccessible::Selected() {
|
|
Accessible* row = Row();
|
|
if (!row) return false;
|
|
|
|
return nsAccUtils::IsARIASelected(row) || nsAccUtils::IsARIASelected(this);
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
// Accessible
|
|
|
|
void ARIAGridCellAccessible::ApplyARIAState(uint64_t* aState) const {
|
|
HyperTextAccessibleWrap::ApplyARIAState(aState);
|
|
|
|
// Return if the gridcell has aria-selected="true".
|
|
if (*aState & states::SELECTED) return;
|
|
|
|
// Check aria-selected="true" on the row.
|
|
Accessible* row = Parent();
|
|
if (!row || row->Role() != roles::ROW) return;
|
|
|
|
nsIContent* rowContent = row->GetContent();
|
|
if (nsAccUtils::HasDefinedARIAToken(rowContent, nsGkAtoms::aria_selected) &&
|
|
!rowContent->AsElement()->AttrValueIs(kNameSpaceID_None,
|
|
nsGkAtoms::aria_selected,
|
|
nsGkAtoms::_false, eCaseMatters))
|
|
*aState |= states::SELECTABLE | states::SELECTED;
|
|
}
|
|
|
|
already_AddRefed<nsIPersistentProperties>
|
|
ARIAGridCellAccessible::NativeAttributes() {
|
|
nsCOMPtr<nsIPersistentProperties> attributes =
|
|
HyperTextAccessibleWrap::NativeAttributes();
|
|
|
|
// Expose "table-cell-index" attribute.
|
|
Accessible* thisRow = Row();
|
|
if (!thisRow) return attributes.forget();
|
|
|
|
int32_t rowIdx = RowIndexFor(thisRow);
|
|
if (rowIdx == -1) { // error
|
|
return attributes.forget();
|
|
}
|
|
|
|
int32_t colIdx = 0, colCount = 0;
|
|
uint32_t childCount = thisRow->ChildCount();
|
|
for (uint32_t childIdx = 0; childIdx < childCount; childIdx++) {
|
|
Accessible* child = thisRow->GetChildAt(childIdx);
|
|
if (child == this) colIdx = colCount;
|
|
|
|
roles::Role role = child->Role();
|
|
if (role == roles::CELL || role == roles::GRID_CELL ||
|
|
role == roles::ROWHEADER || role == roles::COLUMNHEADER)
|
|
colCount++;
|
|
}
|
|
|
|
nsAutoString stringIdx;
|
|
stringIdx.AppendInt(rowIdx * colCount + colIdx);
|
|
nsAccUtils::SetAccAttr(attributes, nsGkAtoms::tableCellIndex, stringIdx);
|
|
|
|
#ifdef DEBUG
|
|
nsAutoString unused;
|
|
attributes->SetStringProperty(NS_LITERAL_CSTRING("cppclass"),
|
|
NS_LITERAL_STRING("ARIAGridCellAccessible"),
|
|
unused);
|
|
#endif
|
|
|
|
return attributes.forget();
|
|
}
|
|
|
|
GroupPos ARIAGridCellAccessible::GroupPosition() {
|
|
int32_t count = 0, index = 0;
|
|
TableAccessible* table = Table();
|
|
if (table &&
|
|
nsCoreUtils::GetUIntAttr(table->AsAccessible()->GetContent(),
|
|
nsGkAtoms::aria_colcount, &count) &&
|
|
nsCoreUtils::GetUIntAttr(mContent, nsGkAtoms::aria_colindex, &index)) {
|
|
return GroupPos(0, index, count);
|
|
}
|
|
|
|
return GroupPos();
|
|
}
|