From d3319fc98280d0866bcbdae0f4d10cb0b204af3b Mon Sep 17 00:00:00 2001 From: James Teh Date: Tue, 15 Feb 2022 05:35:14 +0000 Subject: [PATCH] Bug 1747172: Support cached RemoteAccessible in Pivot text methods. r=eeejay The XPCOM interface and AccVCChangeEvent still only support LocalAccessible. These will need to be updated/refactored in the future. Differential Revision: https://phabricator.services.mozilla.com/D138247 --- accessible/android/AccessibleWrap.cpp | 8 +- accessible/base/Pivot.cpp | 135 +++++++++++++------------- accessible/base/Pivot.h | 12 +-- accessible/base/nsAccessiblePivot.cpp | 14 ++- 4 files changed, 86 insertions(+), 83 deletions(-) diff --git a/accessible/android/AccessibleWrap.cpp b/accessible/android/AccessibleWrap.cpp index 7a1699479738..c8e64b06dd82 100644 --- a/accessible/android/AccessibleWrap.cpp +++ b/accessible/android/AccessibleWrap.cpp @@ -356,14 +356,16 @@ void AccessibleWrap::NavigateText(int32_t aGranularity, int32_t aStartOffset, } int32_t newOffset; - LocalAccessible* newAnchor = nullptr; + Accessible* newAnchorBase = nullptr; if (aForward) { - newAnchor = pivot.NextText(this, &start, &end, pivotGranularity); + newAnchorBase = pivot.NextText(this, &start, &end, pivotGranularity); newOffset = end; } else { - newAnchor = pivot.PrevText(this, &start, &end, pivotGranularity); + newAnchorBase = pivot.PrevText(this, &start, &end, pivotGranularity); newOffset = start; } + LocalAccessible* newAnchor = + newAnchorBase ? newAnchorBase->AsLocal() : nullptr; if (newAnchor && (start != aStartOffset || end != aEndOffset)) { if (IsTextLeaf() && newAnchor == LocalParent()) { diff --git a/accessible/base/Pivot.cpp b/accessible/base/Pivot.cpp index 32516ca48ccf..5e59b696b6bb 100644 --- a/accessible/base/Pivot.cpp +++ b/accessible/base/Pivot.cpp @@ -12,8 +12,11 @@ #include "nsAccessibilityService.h" #include "nsAccUtils.h" +#include "mozilla/a11y/Accessible.h" +#include "mozilla/a11y/HyperTextAccessibleBase.h" #include "mozilla/dom/ChildIterator.h" #include "mozilla/dom/Element.h" +#include "mozilla/StaticPrefs_accessibility.h" using namespace mozilla; using namespace mozilla::a11y; @@ -154,28 +157,28 @@ Accessible* Pivot::SearchForward(Accessible* aAnchor, PivotRule& aRule, return nullptr; } -// TODO: This method does not work for proxy accessibles -HyperTextAccessible* Pivot::SearchForText(LocalAccessible* aAnchor, - bool aBackward) { - if (!mRoot->IsLocal()) { +Accessible* Pivot::SearchForText(Accessible* aAnchor, bool aBackward) { + if (mRoot->IsRemote() && + !StaticPrefs::accessibility_cache_enabled_AtStartup()) { + // Not supported for RemoteAccessible when the cache is disabled. return nullptr; } - LocalAccessible* accessible = aAnchor; + Accessible* accessible = aAnchor; while (true) { - LocalAccessible* child = nullptr; + Accessible* child = nullptr; - while ((child = (aBackward ? accessible->LocalLastChild() - : accessible->LocalFirstChild()))) { + while ((child = (aBackward ? accessible->LastChild() + : accessible->FirstChild()))) { accessible = child; if (child->IsHyperText()) { - return child->AsHyperText(); + return child; } } - LocalAccessible* sibling = nullptr; - LocalAccessible* temp = accessible; + Accessible* sibling = nullptr; + Accessible* temp = accessible; do { - if (temp == mRoot->AsLocal()) { + if (temp == mRoot) { break; } @@ -184,15 +187,15 @@ HyperTextAccessible* Pivot::SearchForText(LocalAccessible* aAnchor, // may be a subtree or a leaf. If it's parent matches, it should // take precedent over a sibling. if (temp != aAnchor && temp->IsHyperText()) { - return temp->AsHyperText(); + return temp; } if (sibling) { break; } - sibling = aBackward ? temp->LocalPrevSibling() : temp->LocalNextSibling(); - } while ((temp = temp->LocalParent())); + sibling = aBackward ? temp->PrevSibling() : temp->NextSibling(); + } while ((temp = temp->Parent())); if (!sibling) { break; @@ -200,7 +203,7 @@ HyperTextAccessible* Pivot::SearchForText(LocalAccessible* aAnchor, accessible = sibling; if (accessible->IsHyperText()) { - return accessible->AsHyperText(); + return accessible; } } @@ -234,23 +237,23 @@ Accessible* Pivot::Last(PivotRule& aRule) { return SearchBackward(lastAcc, aRule, true); } -// TODO: This method does not work for proxy accessibles -LocalAccessible* Pivot::NextText(LocalAccessible* aAnchor, - int32_t* aStartOffset, int32_t* aEndOffset, - int32_t aBoundaryType) { - if (!mRoot->IsLocal()) { +Accessible* Pivot::NextText(Accessible* aAnchor, int32_t* aStartOffset, + int32_t* aEndOffset, int32_t aBoundaryType) { + if (mRoot->IsRemote() && + !StaticPrefs::accessibility_cache_enabled_AtStartup()) { + // Not supported for RemoteAccessible when the cache is disabled. return nullptr; } int32_t tempStart = *aStartOffset, tempEnd = *aEndOffset; - LocalAccessible* tempPosition = aAnchor; + Accessible* tempPosition = aAnchor; // if we're starting on a text leaf, translate the offsets to the // HyperTextAccessible parent and start from there. - if (aAnchor->IsTextLeaf() && aAnchor->LocalParent() && - aAnchor->LocalParent()->IsHyperText()) { - HyperTextAccessible* text = aAnchor->LocalParent()->AsHyperText(); - tempPosition = text; + if (aAnchor->IsTextLeaf() && aAnchor->Parent() && + aAnchor->Parent()->IsHyperText()) { + tempPosition = aAnchor->Parent(); + HyperTextAccessibleBase* text = tempPosition->AsHyperTextBase(); int32_t childOffset = text->GetChildOffset(aAnchor); if (tempEnd == -1) { tempStart = 0; @@ -262,27 +265,27 @@ LocalAccessible* Pivot::NextText(LocalAccessible* aAnchor, while (true) { MOZ_ASSERT(tempPosition); - LocalAccessible* curPosition = tempPosition; - HyperTextAccessible* text = nullptr; + Accessible* curPosition = tempPosition; + HyperTextAccessibleBase* text = nullptr; // Find the nearest text node using a preorder traversal starting from // the current node. - if (!(text = tempPosition->AsHyperText())) { - text = SearchForText(tempPosition, false); - if (!text) { + if (!(text = tempPosition->AsHyperTextBase())) { + tempPosition = SearchForText(tempPosition, false); + if (!tempPosition) { return nullptr; } - if (text != curPosition) { + if (tempPosition != curPosition) { tempStart = tempEnd = -1; } - tempPosition = text; + text = tempPosition->AsHyperTextBase(); } // If the search led to the parent of the node we started on (e.g. when // starting on a text leaf), start the text movement from the end of that // node, otherwise we just default to 0. if (tempEnd == -1) { - tempEnd = text == curPosition->LocalParent() + tempEnd = tempPosition == curPosition->Parent() ? text->GetChildOffset(curPosition) : 0; } @@ -290,7 +293,7 @@ LocalAccessible* Pivot::NextText(LocalAccessible* aAnchor, // If there's no more text on the current node, try to find the next text // node; if there isn't one, bail out. if (tempEnd == static_cast(text->CharacterCount())) { - if (tempPosition == mRoot->AsLocal()) { + if (tempPosition == mRoot) { return nullptr; } @@ -299,7 +302,7 @@ LocalAccessible* Pivot::NextText(LocalAccessible* aAnchor, // offset. Otherwise, do a forward search for the next node to land on // (we don't do this in the first case because we don't want to go to the // subtree). - LocalAccessible* sibling = tempPosition->LocalNextSibling(); + Accessible* sibling = tempPosition->NextSibling(); if (tempPosition->IsLink()) { if (sibling && sibling->IsLink()) { tempStart = tempEnd = -1; @@ -307,7 +310,7 @@ LocalAccessible* Pivot::NextText(LocalAccessible* aAnchor, } else { tempStart = tempPosition->StartOffset(); tempEnd = tempPosition->EndOffset(); - tempPosition = tempPosition->LocalParent(); + tempPosition = tempPosition->Parent(); } } else { tempPosition = SearchForText(tempPosition, false); @@ -349,7 +352,7 @@ LocalAccessible* Pivot::NextText(LocalAccessible* aAnchor, // The offset range we've obtained might have embedded characters in it, // limit the range to the start of the first occurrence of an embedded // character. - LocalAccessible* childAtOffset = nullptr; + Accessible* childAtOffset = nullptr; for (int32_t i = tempStart; i < tempEnd; i++) { childAtOffset = text->GetChildAtOffset(i); if (childAtOffset && childAtOffset->IsHyperText()) { @@ -375,23 +378,23 @@ LocalAccessible* Pivot::NextText(LocalAccessible* aAnchor, } } -// TODO: This method does not work for proxy accessibles -LocalAccessible* Pivot::PrevText(LocalAccessible* aAnchor, - int32_t* aStartOffset, int32_t* aEndOffset, - int32_t aBoundaryType) { - if (!mRoot->IsLocal()) { +Accessible* Pivot::PrevText(Accessible* aAnchor, int32_t* aStartOffset, + int32_t* aEndOffset, int32_t aBoundaryType) { + if (mRoot->IsRemote() && + !StaticPrefs::accessibility_cache_enabled_AtStartup()) { + // Not supported for RemoteAccessible when the cache is disabled. return nullptr; } int32_t tempStart = *aStartOffset, tempEnd = *aEndOffset; - LocalAccessible* tempPosition = aAnchor; + Accessible* tempPosition = aAnchor; // if we're starting on a text leaf, translate the offsets to the // HyperTextAccessible parent and start from there. - if (aAnchor->IsTextLeaf() && aAnchor->LocalParent() && - aAnchor->LocalParent()->IsHyperText()) { - HyperTextAccessible* text = aAnchor->LocalParent()->AsHyperText(); - tempPosition = text; + if (aAnchor->IsTextLeaf() && aAnchor->Parent() && + aAnchor->Parent()->IsHyperText()) { + tempPosition = aAnchor->Parent(); + HyperTextAccessibleBase* text = tempPosition->AsHyperTextBase(); int32_t childOffset = text->GetChildOffset(aAnchor); if (tempStart == -1) { tempStart = nsAccUtils::TextLength(aAnchor); @@ -404,27 +407,28 @@ LocalAccessible* Pivot::PrevText(LocalAccessible* aAnchor, while (true) { MOZ_ASSERT(tempPosition); - LocalAccessible* curPosition = tempPosition; - HyperTextAccessible* text; + Accessible* curPosition = tempPosition; + HyperTextAccessibleBase* text; // Find the nearest text node using a reverse preorder traversal starting // from the current node. - if (!(text = tempPosition->AsHyperText())) { - text = SearchForText(tempPosition, true); - if (!text) { + if (!(text = tempPosition->AsHyperTextBase())) { + tempPosition = SearchForText(tempPosition, true); + if (!tempPosition) { return nullptr; } - if (text != curPosition) { + if (tempPosition != curPosition) { tempStart = tempEnd = -1; } - tempPosition = text; + text = tempPosition->AsHyperTextBase(); } // If the search led to the parent of the node we started on (e.g. when // starting on a text leaf), start the text movement from the end offset // of that node. Otherwise we just default to the last offset in the parent. if (tempStart == -1) { - if (tempPosition != curPosition && text == curPosition->LocalParent()) { + if (tempPosition != curPosition && + tempPosition == curPosition->Parent()) { tempStart = text->GetChildOffset(curPosition) + nsAccUtils::TextLength(curPosition); } else { @@ -435,7 +439,7 @@ LocalAccessible* Pivot::PrevText(LocalAccessible* aAnchor, // If there's no more text on the current node, try to find the previous // text node; if there isn't one, bail out. if (tempStart == 0) { - if (tempPosition == mRoot->AsLocal()) { + if (tempPosition == mRoot) { return nullptr; } @@ -444,25 +448,25 @@ LocalAccessible* Pivot::PrevText(LocalAccessible* aAnchor, // offset. Otherwise, do a forward search for the next node to land on // (we don't do this in the first case because we don't want to go to the // subtree). - LocalAccessible* sibling = tempPosition->LocalPrevSibling(); + Accessible* sibling = tempPosition->PrevSibling(); if (tempPosition->IsLink()) { if (sibling && sibling->IsLink()) { - HyperTextAccessible* siblingText = sibling->AsHyperText(); + HyperTextAccessibleBase* siblingText = sibling->AsHyperTextBase(); tempStart = tempEnd = siblingText ? siblingText->CharacterCount() : -1; tempPosition = sibling; } else { tempStart = tempPosition->StartOffset(); tempEnd = tempPosition->EndOffset(); - tempPosition = tempPosition->LocalParent(); + tempPosition = tempPosition->Parent(); } } else { - HyperTextAccessible* tempText = SearchForText(tempPosition, true); - if (!tempText) { + tempPosition = SearchForText(tempPosition, true); + if (!tempPosition) { return nullptr; } - tempPosition = tempText; + HyperTextAccessibleBase* tempText = tempPosition->AsHyperTextBase(); tempStart = tempEnd = tempText->CharacterCount(); } continue; @@ -505,7 +509,7 @@ LocalAccessible* Pivot::PrevText(LocalAccessible* aAnchor, // The offset range we've obtained might have embedded characters in it, // limit the range to the start of the last occurrence of an embedded // character. - LocalAccessible* childAtOffset = nullptr; + Accessible* childAtOffset = nullptr; for (int32_t i = tempEnd - 1; i >= tempStart; i--) { childAtOffset = text->GetChildAtOffset(i); if (childAtOffset && !childAtOffset->IsText()) { @@ -519,7 +523,8 @@ LocalAccessible* Pivot::PrevText(LocalAccessible* aAnchor, if (childAtOffset && !childAtOffset->IsText() && tempEnd == static_cast(childAtOffset->EndOffset())) { tempPosition = childAtOffset; - tempStart = tempEnd = childAtOffset->AsHyperText()->CharacterCount(); + tempStart = tempEnd = static_cast( + childAtOffset->AsHyperTextBase()->CharacterCount()); continue; } diff --git a/accessible/base/Pivot.h b/accessible/base/Pivot.h index d326993374b0..990444abd9c0 100644 --- a/accessible/base/Pivot.h +++ b/accessible/base/Pivot.h @@ -13,8 +13,6 @@ namespace mozilla { namespace a11y { -class LocalAccessible; -class HyperTextAccessible; class DocAccessible; class Accessible; @@ -56,12 +54,12 @@ class Pivot final { Accessible* Last(PivotRule& aRule); // Return the next range of text according to the boundary type. - LocalAccessible* NextText(LocalAccessible* aAnchor, int32_t* aStartOffset, - int32_t* aEndOffset, int32_t aBoundaryType); + Accessible* NextText(Accessible* aAnchor, int32_t* aStartOffset, + int32_t* aEndOffset, int32_t aBoundaryType); // Return the previous range of text according to the boundary type. - LocalAccessible* PrevText(LocalAccessible* aAnchor, int32_t* aStartOffset, - int32_t* aEndOffset, int32_t aBoundaryType); + Accessible* PrevText(Accessible* aAnchor, int32_t* aStartOffset, + int32_t* aEndOffset, int32_t aBoundaryType); // Return the accessible at the given screen coordinate if it matches the // pivot rule. @@ -80,7 +78,7 @@ class Pivot final { bool aSearchCurrent); // Search in preorder for the first text accessible. - HyperTextAccessible* SearchForText(LocalAccessible* aAnchor, bool aBackward); + Accessible* SearchForText(Accessible* aAnchor, bool aBackward); Accessible* mRoot; }; diff --git a/accessible/base/nsAccessiblePivot.cpp b/accessible/base/nsAccessiblePivot.cpp index 6224a1a35b44..f8f3e424a307 100644 --- a/accessible/base/nsAccessiblePivot.cpp +++ b/accessible/base/nsAccessiblePivot.cpp @@ -321,15 +321,14 @@ nsAccessiblePivot::MoveNextByText(TextBoundaryType aBoundary, Pivot pivot(GetActiveRoot()); int32_t newStart = mStartOffset, newEnd = mEndOffset; - LocalAccessible* newPos = - pivot.NextText(mPosition, &newStart, &newEnd, aBoundary); - if (newPos) { + Accessible* newPos = pivot.NextText(mPosition, &newStart, &newEnd, aBoundary); + if (LocalAccessible* localNewPos = newPos ? newPos->AsLocal() : nullptr) { *aResult = true; int32_t oldStart = mStartOffset, oldEnd = mEndOffset; LocalAccessible* oldPos = mPosition; mStartOffset = newStart; mEndOffset = newEnd; - mPosition = newPos; + mPosition = localNewPos; NotifyOfPivotChange(oldPos, oldStart, oldEnd, nsIAccessiblePivot::REASON_NEXT, aBoundary, (aArgc > 0) ? aIsFromUserInput : true); @@ -349,15 +348,14 @@ nsAccessiblePivot::MovePreviousByText(TextBoundaryType aBoundary, Pivot pivot(GetActiveRoot()); int32_t newStart = mStartOffset, newEnd = mEndOffset; - LocalAccessible* newPos = - pivot.PrevText(mPosition, &newStart, &newEnd, aBoundary); - if (newPos) { + Accessible* newPos = pivot.PrevText(mPosition, &newStart, &newEnd, aBoundary); + if (LocalAccessible* localNewPos = newPos ? newPos->AsLocal() : nullptr) { *aResult = true; int32_t oldStart = mStartOffset, oldEnd = mEndOffset; LocalAccessible* oldPos = mPosition; mStartOffset = newStart; mEndOffset = newEnd; - mPosition = newPos; + mPosition = localNewPos; NotifyOfPivotChange(oldPos, oldStart, oldEnd, nsIAccessiblePivot::REASON_PREV, aBoundary, (aArgc > 0) ? aIsFromUserInput : true);