Bug 1737944 - P9: Make AccGroupInfo use Accessible. r=Jamie

Now that GroupPosition and GetGroupInfo are in Accessible, we can make
AccGroupInfo use the Accessible base class.

With one exception: Tables are still local only. That should be
addressed in bug 1735970.

Differential Revision: https://phabricator.services.mozilla.com/D134212
This commit is contained in:
Eitan Isaacson 2022-01-04 21:01:38 +00:00
parent b7dd36fd8a
commit f8f5a14d7a
4 changed files with 58 additions and 46 deletions

View File

@ -3,7 +3,8 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "AccGroupInfo.h"
#include "LocalAccessible-inl.h"
#include "mozilla/a11y/Accessible.h"
#include "nsAccUtils.h"
#include "TableAccessible.h"
@ -11,7 +12,7 @@
using namespace mozilla::a11y;
AccGroupInfo::AccGroupInfo(const LocalAccessible* aItem, role aRole)
AccGroupInfo::AccGroupInfo(const Accessible* aItem, role aRole)
: mPosInSet(0), mSetSize(0), mParent(nullptr), mItem(aItem), mRole(aRole) {
MOZ_COUNT_CTOR(AccGroupInfo);
Update();
@ -20,7 +21,7 @@ AccGroupInfo::AccGroupInfo(const LocalAccessible* aItem, role aRole)
void AccGroupInfo::Update() {
mParent = nullptr;
LocalAccessible* parent = mItem->LocalParent();
Accessible* parent = mItem->Parent();
if (!parent) return;
int32_t indexInParent = mItem->IndexInParent();
@ -36,7 +37,7 @@ void AccGroupInfo::Update() {
// Compute position in set.
mPosInSet = 1;
for (int32_t idx = indexInParent - 1; idx >= 0; idx--) {
LocalAccessible* sibling = parent->LocalChildAt(idx);
Accessible* sibling = parent->ChildAt(idx);
roles::Role siblingRole = sibling->Role();
// If the sibling is separator then the group is ended.
@ -82,7 +83,7 @@ void AccGroupInfo::Update() {
mSetSize = mPosInSet;
for (uint32_t idx = indexInParent + 1; idx < siblingCount; idx++) {
LocalAccessible* sibling = parent->LocalChildAt(idx);
Accessible* sibling = parent->ChildAt(idx);
roles::Role siblingRole = sibling->Role();
@ -130,7 +131,7 @@ void AccGroupInfo::Update() {
// the previous tree item of the group is a conceptual parent of the tree
// item.
if (mRole == roles::OUTLINEITEM) {
LocalAccessible* parentPrevSibling = parent->LocalPrevSibling();
Accessible* parentPrevSibling = parent->PrevSibling();
if (parentPrevSibling && parentPrevSibling->Role() == mRole) {
mParent = parentPrevSibling;
return;
@ -141,13 +142,12 @@ void AccGroupInfo::Update() {
// the parent of the item will be a group and containing item of the group is
// a conceptual parent of the item.
if (mRole == roles::LISTITEM || mRole == roles::OUTLINEITEM) {
LocalAccessible* grandParent = parent->LocalParent();
Accessible* grandParent = parent->Parent();
if (grandParent && grandParent->Role() == mRole) mParent = grandParent;
}
}
AccGroupInfo* AccGroupInfo::CreateGroupInfo(
const LocalAccessible* aAccessible) {
AccGroupInfo* AccGroupInfo::CreateGroupInfo(const Accessible* aAccessible) {
mozilla::a11y::role role = aAccessible->Role();
if (role != mozilla::a11y::roles::ROW &&
role != mozilla::a11y::roles::OUTLINEITEM &&
@ -170,15 +170,15 @@ AccGroupInfo* AccGroupInfo::CreateGroupInfo(
return info;
}
LocalAccessible* AccGroupInfo::FirstItemOf(const LocalAccessible* aContainer) {
Accessible* AccGroupInfo::FirstItemOf(const Accessible* aContainer) {
// ARIA tree can be arranged by ARIA groups case #1 (previous sibling of a
// group is a parent) or by aria-level.
a11y::role containerRole = aContainer->Role();
LocalAccessible* item = aContainer->LocalNextSibling();
Accessible* item = aContainer->NextSibling();
if (item) {
if (containerRole == roles::OUTLINEITEM &&
item->Role() == roles::GROUPING) {
item = item->LocalFirstChild();
item = item->FirstChild();
}
if (item) {
@ -191,13 +191,13 @@ LocalAccessible* AccGroupInfo::FirstItemOf(const LocalAccessible* aContainer) {
// ARIA list and tree can be arranged by ARIA groups case #2 (group is
// a child of an item).
item = aContainer->LocalLastChild();
item = aContainer->LastChild();
if (!item) return nullptr;
if (item->Role() == roles::GROUPING &&
(containerRole == roles::LISTITEM ||
containerRole == roles::OUTLINEITEM)) {
item = item->LocalFirstChild();
item = item->FirstChild();
if (item) {
AccGroupInfo* itemGroupInfo = item->GetOrCreateGroupInfo();
if (itemGroupInfo && itemGroupInfo->ConceptualParent() == aContainer) {
@ -207,37 +207,44 @@ LocalAccessible* AccGroupInfo::FirstItemOf(const LocalAccessible* aContainer) {
}
// Otherwise, it can be a direct child if the container is a list or tree.
item = aContainer->LocalFirstChild();
item = aContainer->FirstChild();
if (ShouldReportRelations(item->Role(), containerRole)) return item;
return nullptr;
}
uint32_t AccGroupInfo::TotalItemCount(LocalAccessible* aContainer,
uint32_t AccGroupInfo::TotalItemCount(Accessible* aContainer,
bool* aIsHierarchical) {
uint32_t itemCount = 0;
switch (aContainer->Role()) {
case roles::TABLE:
if (nsCoreUtils::GetUIntAttr(aContainer->GetContent(),
if (!aContainer->IsLocal()) {
break;
}
if (nsCoreUtils::GetUIntAttr(aContainer->AsLocal()->GetContent(),
nsGkAtoms::aria_rowcount,
(int32_t*)&itemCount)) {
break;
}
if (TableAccessible* tableAcc = aContainer->AsTable()) {
if (TableAccessible* tableAcc = aContainer->AsLocal()->AsTable()) {
return tableAcc->RowCount();
}
break;
case roles::ROW:
if (LocalAccessible* table = nsAccUtils::TableFor(aContainer)) {
if (!aContainer->IsLocal()) {
break;
}
if (LocalAccessible* table =
nsAccUtils::TableFor(aContainer->AsLocal())) {
if (nsCoreUtils::GetUIntAttr(table->GetContent(),
nsGkAtoms::aria_colcount,
(int32_t*)&itemCount)) {
break;
}
if (TableAccessible* tableAcc = table->AsTable()) {
if (TableAccessible* tableAcc = table->AsLocal()->AsTable()) {
return tableAcc->ColCount();
}
}
@ -256,12 +263,12 @@ uint32_t AccGroupInfo::TotalItemCount(LocalAccessible* aContainer,
case roles::EDITCOMBOBOX:
case roles::RADIO_GROUP:
case roles::PAGETABLIST: {
LocalAccessible* childItem = AccGroupInfo::FirstItemOf(aContainer);
Accessible* childItem = AccGroupInfo::FirstItemOf(aContainer);
if (!childItem) {
childItem = aContainer->LocalFirstChild();
childItem = aContainer->FirstChild();
if (childItem && childItem->IsTextLeaf()) {
// First child can be a text leaf, check its sibling for an item.
childItem = childItem->LocalNextSibling();
childItem = childItem->NextSibling();
}
}
@ -281,17 +288,17 @@ uint32_t AccGroupInfo::TotalItemCount(LocalAccessible* aContainer,
return itemCount;
}
LocalAccessible* AccGroupInfo::NextItemTo(LocalAccessible* aItem) {
AccGroupInfo* groupInfo = aItem->GetGroupInfo();
Accessible* AccGroupInfo::NextItemTo(Accessible* aItem) {
AccGroupInfo* groupInfo = aItem->GetOrCreateGroupInfo();
if (!groupInfo) return nullptr;
// If the item in middle of the group then search next item in siblings.
if (groupInfo->PosInSet() >= groupInfo->SetSize()) return nullptr;
LocalAccessible* parent = aItem->LocalParent();
Accessible* parent = aItem->Parent();
uint32_t childCount = parent->ChildCount();
for (uint32_t idx = aItem->IndexInParent() + 1; idx < childCount; idx++) {
LocalAccessible* nextItem = parent->LocalChildAt(idx);
Accessible* nextItem = parent->ChildAt(idx);
AccGroupInfo* nextGroupInfo = nextItem->GetOrCreateGroupInfo();
if (nextGroupInfo &&
nextGroupInfo->ConceptualParent() == groupInfo->ConceptualParent()) {
@ -314,8 +321,7 @@ bool AccGroupInfo::ShouldReportRelations(role aRole, role aParentRole) {
return false;
}
int32_t AccGroupInfo::GetARIAOrDefaultLevel(
const LocalAccessible* aAccessible) {
int32_t AccGroupInfo::GetARIAOrDefaultLevel(const Accessible* aAccessible) {
int32_t level = 0;
aAccessible->ARIAGroupPosition(&level, nullptr, nullptr);

View File

@ -11,7 +11,7 @@
namespace mozilla {
namespace a11y {
class LocalAccessible;
class Accessible;
/**
* Calculate and store group information.
@ -38,7 +38,7 @@ class AccGroupInfo {
* Return a direct or logical parent of the accessible that this group info is
* created for.
*/
LocalAccessible* ConceptualParent() const { return mParent; }
Accessible* ConceptualParent() const { return mParent; }
/**
* Update group information.
@ -48,27 +48,26 @@ class AccGroupInfo {
/**
* Create group info.
*/
static AccGroupInfo* CreateGroupInfo(const LocalAccessible* aAccessible);
static AccGroupInfo* CreateGroupInfo(const Accessible* aAccessible);
/**
* Return a first item for the given container.
*/
static LocalAccessible* FirstItemOf(const LocalAccessible* aContainer);
static Accessible* FirstItemOf(const Accessible* aContainer);
/**
* Return total number of items in container, and if it is has nested
* collections.
*/
static uint32_t TotalItemCount(LocalAccessible* aContainer,
bool* aIsHierarchical);
static uint32_t TotalItemCount(Accessible* aContainer, bool* aIsHierarchical);
/**
* Return next item of the same group to the given item.
*/
static LocalAccessible* NextItemTo(LocalAccessible* aItem);
static Accessible* NextItemTo(Accessible* aItem);
protected:
AccGroupInfo(const LocalAccessible* aItem, a11y::role aRole);
AccGroupInfo(const Accessible* aItem, a11y::role aRole);
private:
AccGroupInfo(const AccGroupInfo&) = delete;
@ -98,12 +97,12 @@ class AccGroupInfo {
* Return ARIA level value or the default one if ARIA is missed for the
* given accessible.
*/
static int32_t GetARIAOrDefaultLevel(const LocalAccessible* aAccessible);
static int32_t GetARIAOrDefaultLevel(const Accessible* aAccessible);
uint32_t mPosInSet;
uint32_t mSetSize;
LocalAccessible* mParent;
const LocalAccessible* mItem;
Accessible* mParent;
const Accessible* mItem;
a11y::role mRole;
};

View File

@ -293,12 +293,18 @@ LocalAccessible* SingleAccIterator::Next() {
LocalAccessible* ItemIterator::Next() {
if (mContainer) {
mAnchor = AccGroupInfo::FirstItemOf(mContainer);
Accessible* first = AccGroupInfo::FirstItemOf(mContainer);
mAnchor = first ? first->AsLocal() : nullptr;
mContainer = nullptr;
return mAnchor;
}
return mAnchor ? (mAnchor = AccGroupInfo::NextItemTo(mAnchor)) : nullptr;
if (mAnchor) {
Accessible* next = AccGroupInfo::NextItemTo(mAnchor);
mAnchor = next ? next->AsLocal() : nullptr;
}
return mAnchor;
}
////////////////////////////////////////////////////////////////////////////////

View File

@ -1978,11 +1978,12 @@ Relation LocalAccessible::RelationByType(RelationType aType) const {
if (roleMapEntry && (roleMapEntry->role == roles::OUTLINEITEM ||
roleMapEntry->role == roles::LISTITEM ||
roleMapEntry->role == roles::ROW)) {
LocalAccessible* parent = const_cast<LocalAccessible*>(this)
Accessible* parent = const_cast<LocalAccessible*>(this)
->GetOrCreateGroupInfo()
->ConceptualParent();
if (parent) {
rel.AppendTarget(parent);
MOZ_ASSERT(parent->IsLocal());
rel.AppendTarget(parent->AsLocal());
}
}