Bug 1652809: Convert Pivot framework to use AccessibleOrProxy objects r=eeejay

Differential Revision: https://phabricator.services.mozilla.com/D83671
This commit is contained in:
Morgan Reschenberg 2020-07-28 22:35:24 +00:00
Родитель 2c9e686a8d
Коммит 95e4d6df8e
9 изменённых файлов: 257 добавлений и 133 удалений

Просмотреть файл

@ -296,10 +296,13 @@ bool AccessibleWrap::GetSelectionBounds(int32_t* aStartOffset,
void AccessibleWrap::Pivot(int32_t aGranularity, bool aForward,
bool aInclusive) {
a11y::Pivot pivot(RootAccessible());
AccessibleOrProxy accOrProxyRoot = AccessibleOrProxy(RootAccessible());
a11y::Pivot pivot(accOrProxyRoot);
TraversalRule rule(aGranularity);
Accessible* result = aForward ? pivot.Next(this, rule, aInclusive)
: pivot.Prev(this, rule, aInclusive);
AccessibleOrProxy accOrProxy = AccessibleOrProxy(this);
Accessible* result =
aForward ? pivot.Next(accOrProxy, rule, aInclusive).AsAccessible()
: pivot.Prev(accOrProxy, rule, aInclusive).AsAccessible();
if (result && (result != this || aInclusive)) {
PivotMoveReason reason = aForward ? nsIAccessiblePivot::REASON_NEXT
: nsIAccessiblePivot::REASON_PREV;
@ -314,7 +317,7 @@ void AccessibleWrap::ExploreByTouch(float aX, float aY) {
a11y::Pivot pivot(RootAccessible());
TraversalRule rule;
Accessible* result = pivot.AtPoint(aX, aY, rule);
Accessible* result = pivot.AtPoint(aX, aY, rule).AsAccessible();
if (result && result != this) {
RefPtr<AccEvent> event =

Просмотреть файл

@ -5,6 +5,7 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "Accessible-inl.h"
#include "AccessibleOrProxy.h"
#include "DocAccessibleChild.h"
#include "DocAccessibleWrap.h"
#include "nsIDocShell.h"
@ -157,10 +158,11 @@ void DocAccessibleWrap::CacheViewportCallback(nsITimer* aTimer,
}
if (docAcc->mCachePivotBoundaries) {
a11y::Pivot pivot(docAcc);
AccessibleOrProxy accOrProxy = AccessibleOrProxy(docAcc);
a11y::Pivot pivot(accOrProxy);
TraversalRule rule(java::SessionAccessibility::HTML_GRANULARITY_DEFAULT);
Accessible* first = pivot.First(rule);
Accessible* last = pivot.Last(rule);
Accessible* first = pivot.First(rule).AsAccessible();
Accessible* last = pivot.Last(rule).AsAccessible();
// If first/last are null, pass the root document as pivot boundary.
if (IPCAccessibilityActive()) {

Просмотреть файл

@ -25,7 +25,10 @@ TraversalRule::TraversalRule()
TraversalRule::TraversalRule(int32_t aGranularity)
: mGranularity(aGranularity) {}
uint16_t TraversalRule::Match(Accessible* aAccessible) {
uint16_t TraversalRule::Match(const AccessibleOrProxy& aAccOrProxy) {
MOZ_ASSERT(aAccOrProxy.IsAccessible(),
"Should only receive accessibles when processing on android.");
Accessible* aAccessible = aAccOrProxy.AsAccessible();
uint16_t result = nsIAccessibleTraversalRule::FILTER_IGNORE;
if (nsAccUtils::MustPrune(aAccessible)) {

Просмотреть файл

@ -24,7 +24,7 @@ class TraversalRule final : public PivotRule {
~TraversalRule() = default;
virtual uint16_t Match(Accessible* aAccessible) override;
virtual uint16_t Match(const AccessibleOrProxy& aAccOrProxy) override;
private:
bool IsSingleLineage(Accessible* aAccessible);

Просмотреть файл

@ -61,6 +61,11 @@ class AccessibleOrProxy {
return AsAccessible()->ChildCount();
}
/**
* Return true if the object has children, false otherwise
*/
bool HasChildren() const { return ChildCount() > 0; }
/**
* Return the child object either an accessible or a proxied accessible at
* the given index.
@ -110,6 +115,28 @@ class AccessibleOrProxy {
return AsAccessible()->LastChild();
}
/**
* Return the next sibling object.
*/
AccessibleOrProxy NextSibling() {
if (IsProxy()) {
return AsProxy()->NextSibling();
}
return AsAccessible()->NextSibling();
}
/**
* Return the prev sibling object.
*/
AccessibleOrProxy PrevSibling() {
if (IsProxy()) {
return AsProxy()->PrevSibling();
}
return AsAccessible()->PrevSibling();
}
role Role() const {
if (IsProxy()) {
return AsProxy()->Role();

Просмотреть файл

@ -21,18 +21,21 @@ using namespace mozilla::a11y;
// Pivot
////////////////////////////////////////////////////////////////////////////////
Pivot::Pivot(Accessible* aRoot) : mRoot(aRoot) { MOZ_COUNT_CTOR(Pivot); }
Pivot::Pivot(const AccessibleOrProxy& aRoot) : mRoot(aRoot) {
MOZ_COUNT_CTOR(Pivot);
}
Pivot::~Pivot() { MOZ_COUNT_DTOR(Pivot); }
Accessible* Pivot::AdjustStartPosition(Accessible* aAnchor, PivotRule& aRule,
AccessibleOrProxy Pivot::AdjustStartPosition(AccessibleOrProxy& aAnchor,
PivotRule& aRule,
uint16_t* aFilterResult) {
Accessible* matched = aAnchor;
AccessibleOrProxy matched = aAnchor;
*aFilterResult = aRule.Match(aAnchor);
if (aAnchor != mRoot) {
for (Accessible* temp = aAnchor->Parent(); temp && temp != mRoot;
temp = temp->Parent()) {
for (AccessibleOrProxy temp = aAnchor.Parent();
!temp.IsNull() && temp != mRoot; temp = temp.Parent()) {
uint16_t filtered = aRule.Match(temp);
if (filtered & nsIAccessibleTraversalRule::FILTER_IGNORE_SUBTREE) {
*aFilterResult = filtered;
@ -44,111 +47,120 @@ Accessible* Pivot::AdjustStartPosition(Accessible* aAnchor, PivotRule& aRule,
return matched;
}
Accessible* Pivot::SearchBackward(Accessible* aAnchor, PivotRule& aRule,
bool aSearchCurrent) {
// Initial position could be unset, in that case return null.
if (!aAnchor) {
return nullptr;
AccessibleOrProxy Pivot::SearchBackward(AccessibleOrProxy& aAnchor,
PivotRule& aRule, bool aSearchCurrent) {
// Initial position could be unset, in that case return null AoP.
if (aAnchor.IsNull()) {
return aAnchor;
}
uint16_t filtered = nsIAccessibleTraversalRule::FILTER_IGNORE;
Accessible* accessible = AdjustStartPosition(aAnchor, aRule, &filtered);
AccessibleOrProxy accOrProxy = AdjustStartPosition(aAnchor, aRule, &filtered);
if (aSearchCurrent && (filtered & nsIAccessibleTraversalRule::FILTER_MATCH)) {
return accessible;
return accOrProxy;
}
while (accessible != mRoot) {
Accessible* parent = accessible->Parent();
int32_t idxInParent = accessible->IndexInParent();
while (accOrProxy != mRoot) {
AccessibleOrProxy parent = accOrProxy.Parent();
int32_t idxInParent = accOrProxy.IndexInParent();
while (idxInParent > 0) {
if (!(accessible = parent->GetChildAt(--idxInParent))) {
accOrProxy = parent.ChildAt(--idxInParent);
if (accOrProxy.IsNull()) {
continue;
}
filtered = aRule.Match(accessible);
filtered = aRule.Match(accOrProxy);
Accessible* lastChild = nullptr;
AccessibleOrProxy lastChild = accOrProxy.LastChild();
while (!(filtered & nsIAccessibleTraversalRule::FILTER_IGNORE_SUBTREE) &&
(lastChild = accessible->LastChild())) {
parent = accessible;
accessible = lastChild;
idxInParent = accessible->IndexInParent();
filtered = aRule.Match(accessible);
!lastChild.IsNull()) {
parent = accOrProxy;
accOrProxy = lastChild;
idxInParent = accOrProxy.IndexInParent();
filtered = aRule.Match(accOrProxy);
lastChild = accOrProxy.LastChild();
}
if (filtered & nsIAccessibleTraversalRule::FILTER_MATCH) {
return accessible;
return accOrProxy;
}
}
if (!(accessible = parent)) {
accOrProxy = parent;
if (accOrProxy.IsNull()) {
break;
}
filtered = aRule.Match(accessible);
filtered = aRule.Match(accOrProxy);
if (filtered & nsIAccessibleTraversalRule::FILTER_MATCH) {
return accessible;
return accOrProxy;
}
}
return nullptr;
return AccessibleOrProxy();
}
Accessible* Pivot::SearchForward(Accessible* aAnchor, PivotRule& aRule,
bool aSearchCurrent) {
AccessibleOrProxy Pivot::SearchForward(AccessibleOrProxy& aAnchor,
PivotRule& aRule, bool aSearchCurrent) {
// Initial position could be not set, in that case begin search from root.
Accessible* accessible = aAnchor ? aAnchor : mRoot;
AccessibleOrProxy accOrProxy = !aAnchor.IsNull() ? aAnchor : mRoot;
uint16_t filtered = nsIAccessibleTraversalRule::FILTER_IGNORE;
accessible = AdjustStartPosition(accessible, aRule, &filtered);
accOrProxy = AdjustStartPosition(accOrProxy, aRule, &filtered);
if (aSearchCurrent && (filtered & nsIAccessibleTraversalRule::FILTER_MATCH)) {
return accessible;
return accOrProxy;
}
while (true) {
Accessible* firstChild = nullptr;
AccessibleOrProxy firstChild = accOrProxy.FirstChild();
while (!(filtered & nsIAccessibleTraversalRule::FILTER_IGNORE_SUBTREE) &&
(firstChild = accessible->FirstChild())) {
accessible = firstChild;
filtered = aRule.Match(accessible);
!firstChild.IsNull()) {
accOrProxy = firstChild;
filtered = aRule.Match(accOrProxy);
if (filtered & nsIAccessibleTraversalRule::FILTER_MATCH) {
return accessible;
return accOrProxy;
}
firstChild = accOrProxy.FirstChild();
}
Accessible* sibling = nullptr;
Accessible* temp = accessible;
AccessibleOrProxy sibling = AccessibleOrProxy();
AccessibleOrProxy temp = accOrProxy;
do {
if (temp == mRoot) {
break;
}
sibling = temp->NextSibling();
sibling = temp.NextSibling();
if (sibling) {
if (!sibling.IsNull()) {
break;
}
} while ((temp = temp->Parent()));
temp = temp.Parent();
} while (!temp.IsNull());
if (!sibling) {
if (sibling.IsNull()) {
break;
}
accessible = sibling;
filtered = aRule.Match(accessible);
accOrProxy = sibling;
filtered = aRule.Match(accOrProxy);
if (filtered & nsIAccessibleTraversalRule::FILTER_MATCH) {
return accessible;
return accOrProxy;
}
}
return AccessibleOrProxy();
}
// TODO: This method does not work for proxy accessibles
HyperTextAccessible* Pivot::SearchForText(Accessible* aAnchor, bool aBackward) {
if (!mRoot.IsAccessible()) {
return nullptr;
}
HyperTextAccessible* Pivot::SearchForText(Accessible* aAnchor, bool aBackward) {
Accessible* accessible = aAnchor;
while (true) {
Accessible* child = nullptr;
@ -164,7 +176,7 @@ HyperTextAccessible* Pivot::SearchForText(Accessible* aAnchor, bool aBackward) {
Accessible* sibling = nullptr;
Accessible* temp = accessible;
do {
if (temp == mRoot) {
if (temp == mRoot.AsAccessible()) {
break;
}
@ -196,35 +208,40 @@ HyperTextAccessible* Pivot::SearchForText(Accessible* aAnchor, bool aBackward) {
return nullptr;
}
Accessible* Pivot::Next(Accessible* aAnchor, PivotRule& aRule,
AccessibleOrProxy Pivot::Next(AccessibleOrProxy& aAnchor, PivotRule& aRule,
bool aIncludeStart) {
return SearchForward(aAnchor, aRule, aIncludeStart);
}
Accessible* Pivot::Prev(Accessible* aAnchor, PivotRule& aRule,
AccessibleOrProxy Pivot::Prev(AccessibleOrProxy& aAnchor, PivotRule& aRule,
bool aIncludeStart) {
return SearchBackward(aAnchor, aRule, aIncludeStart);
}
Accessible* Pivot::First(PivotRule& aRule) {
AccessibleOrProxy Pivot::First(PivotRule& aRule) {
return SearchForward(mRoot, aRule, true);
}
Accessible* Pivot::Last(PivotRule& aRule) {
Accessible* lastAccessible = mRoot;
AccessibleOrProxy Pivot::Last(PivotRule& aRule) {
AccessibleOrProxy lastAccOrProxy = mRoot;
// First go to the last accessible in pre-order
while (lastAccessible->HasChildren()) {
lastAccessible = lastAccessible->LastChild();
while (lastAccOrProxy.HasChildren()) {
lastAccOrProxy = lastAccOrProxy.LastChild();
}
// Search backwards from last accessible and find the last occurrence in the
// doc
return SearchBackward(lastAccessible, aRule, true);
return SearchBackward(lastAccOrProxy, aRule, true);
}
// TODO: This method does not work for proxy accessibles
Accessible* Pivot::NextText(Accessible* aAnchor, int32_t* aStartOffset,
int32_t* aEndOffset, int32_t aBoundaryType) {
if (!mRoot.IsAccessible()) {
return nullptr;
}
int32_t tempStart = *aStartOffset, tempEnd = *aEndOffset;
Accessible* tempPosition = aAnchor;
@ -272,7 +289,7 @@ Accessible* Pivot::NextText(Accessible* aAnchor, int32_t* aStartOffset,
// 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<int32_t>(text->CharacterCount())) {
if (tempPosition == mRoot) {
if (tempPosition == mRoot.AsAccessible()) {
return nullptr;
}
@ -357,8 +374,13 @@ Accessible* Pivot::NextText(Accessible* aAnchor, int32_t* aStartOffset,
}
}
// TODO: This method does not work for proxy accessibles
Accessible* Pivot::PrevText(Accessible* aAnchor, int32_t* aStartOffset,
int32_t* aEndOffset, int32_t aBoundaryType) {
if (!mRoot.IsAccessible()) {
return nullptr;
}
int32_t tempStart = *aStartOffset, tempEnd = *aEndOffset;
Accessible* tempPosition = aAnchor;
@ -411,7 +433,7 @@ Accessible* Pivot::PrevText(Accessible* aAnchor, int32_t* aStartOffset,
// 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) {
if (tempPosition == mRoot.AsAccessible()) {
return nullptr;
}
@ -507,20 +529,24 @@ Accessible* Pivot::PrevText(Accessible* aAnchor, int32_t* aStartOffset,
}
}
Accessible* Pivot::AtPoint(int32_t aX, int32_t aY, PivotRule& aRule) {
Accessible* match = nullptr;
Accessible* child = mRoot->ChildAtPoint(aX, aY, Accessible::eDeepestChild);
while (child && mRoot != child) {
AccessibleOrProxy Pivot::AtPoint(int32_t aX, int32_t aY, PivotRule& aRule) {
AccessibleOrProxy match = AccessibleOrProxy();
AccessibleOrProxy child =
mRoot.ChildAtPoint(aX, aY, Accessible::eDeepestChild);
while (!child.IsNull() && (mRoot != child)) {
uint16_t filtered = aRule.Match(child);
// Ignore any matching nodes that were below this one
if (filtered & nsIAccessibleTraversalRule::FILTER_IGNORE_SUBTREE) {
match = nullptr;
match = AccessibleOrProxy();
}
// Match if no node below this is a match
if ((filtered & nsIAccessibleTraversalRule::FILTER_MATCH) && !match) {
nsIntRect childRect = child->Bounds();
if ((filtered & nsIAccessibleTraversalRule::FILTER_MATCH) &&
match.IsNull()) {
nsIntRect childRect = child.IsAccessible()
? child.AsAccessible()->Bounds()
: child.AsProxy()->Bounds();
// Double-check child's bounds since the deepest child may have been out
// of bounds. This assures we don't return a false positive.
if (childRect.Contains(aX, aY)) {
@ -528,7 +554,7 @@ Accessible* Pivot::AtPoint(int32_t aX, int32_t aY, PivotRule& aRule) {
}
}
child = child->Parent();
child = child.Parent();
}
return match;
@ -538,14 +564,28 @@ Accessible* Pivot::AtPoint(int32_t aX, int32_t aY, PivotRule& aRule) {
PivotRoleRule::PivotRoleRule(mozilla::a11y::role aRole) : mRole(aRole) {}
uint16_t PivotRoleRule::Match(Accessible* aAccessible) {
uint16_t PivotRoleRule::Match(const AccessibleOrProxy& aAccOrProxy) {
uint16_t result = nsIAccessibleTraversalRule::FILTER_IGNORE;
if (nsAccUtils::MustPrune(aAccessible)) {
if (nsAccUtils::MustPrune(aAccOrProxy)) {
result |= nsIAccessibleTraversalRule::FILTER_IGNORE_SUBTREE;
}
if (aAccessible->Role() == mRole) {
if (aAccOrProxy.Role() == mRole) {
result |= nsIAccessibleTraversalRule::FILTER_MATCH;
}
return result;
}
// Match All Rule
uint16_t PivotMatchAllRule::Match(const AccessibleOrProxy& aAccOrProxy) {
uint16_t result = nsIAccessibleTraversalRule::FILTER_IGNORE;
if (nsAccUtils::MustPrune(aAccOrProxy)) {
result |= nsIAccessibleTraversalRule::FILTER_IGNORE_SUBTREE;
} else {
result |= nsIAccessibleTraversalRule::FILTER_MATCH;
}

Просмотреть файл

@ -9,6 +9,7 @@
#include <stdint.h>
#include "Role.h"
#include "mozilla/dom/ChildIterator.h"
#include "AccessibleOrProxy.h"
namespace mozilla {
namespace a11y {
@ -23,7 +24,7 @@ class PivotRule {
// nsIAccessibleTraversalRule: FILTER_IGNORE (0x0): Don't match this
// accessible. FILTER_MATCH (0x1): Match this accessible FILTER_IGNORE_SUBTREE
// (0x2): Ignore accessible's subtree.
virtual uint16_t Match(Accessible* aAccessible) = 0;
virtual uint16_t Match(const AccessibleOrProxy& aAccOrProxy) = 0;
};
// The Pivot class is used for searching for accessible nodes in a given subtree
@ -31,7 +32,7 @@ class PivotRule {
// this class is meant to be used primarily on the stack.
class Pivot final {
public:
explicit Pivot(Accessible* aRoot);
explicit Pivot(const AccessibleOrProxy& aRoot);
Pivot() = delete;
Pivot(const Pivot&) = delete;
Pivot& operator=(const Pivot&) = delete;
@ -40,19 +41,19 @@ class Pivot final {
// Return the next accessible after aAnchor in pre-order that matches the
// given rule. If aIncludeStart, return aAnchor if it matches the rule.
Accessible* Next(Accessible* aAnchor, PivotRule& aRule,
AccessibleOrProxy Next(AccessibleOrProxy& aAnchor, PivotRule& aRule,
bool aIncludeStart = false);
// Return the previous accessible before aAnchor in pre-order that matches the
// given rule. If aIncludeStart, return aAnchor if it matches the rule.
Accessible* Prev(Accessible* aAnchor, PivotRule& aRule,
AccessibleOrProxy Prev(AccessibleOrProxy& aAnchor, PivotRule& aRule,
bool aIncludeStart = false);
// Return the first accessible within the root that matches the pivot rule.
Accessible* First(PivotRule& aRule);
AccessibleOrProxy First(PivotRule& aRule);
// Return the last accessible within the root that matches the pivot rule.
Accessible* Last(PivotRule& aRule);
AccessibleOrProxy Last(PivotRule& aRule);
// Return the next range of text according to the boundary type.
Accessible* NextText(Accessible* aAnchor, int32_t* aStartOffset,
@ -64,24 +65,25 @@ class Pivot final {
// Return the accessible at the given screen coordinate if it matches the
// pivot rule.
Accessible* AtPoint(int32_t aX, int32_t aY, PivotRule& aRule);
AccessibleOrProxy AtPoint(int32_t aX, int32_t aY, PivotRule& aRule);
private:
Accessible* AdjustStartPosition(Accessible* aAnchor, PivotRule& aRule,
AccessibleOrProxy AdjustStartPosition(AccessibleOrProxy& aAnchor,
PivotRule& aRule,
uint16_t* aFilterResult);
// Search in preorder for the first accessible to match the rule.
Accessible* SearchForward(Accessible* aAnchor, PivotRule& aRule,
AccessibleOrProxy SearchForward(AccessibleOrProxy& aAnchor, PivotRule& aRule,
bool aSearchCurrent);
// Reverse search in preorder for the first accessible to match the rule.
Accessible* SearchBackward(Accessible* aAnchor, PivotRule& aRule,
AccessibleOrProxy SearchBackward(AccessibleOrProxy& aAnchor, PivotRule& aRule,
bool aSearchCurrent);
// Search in preorder for the first text accessible.
HyperTextAccessible* SearchForText(Accessible* aAnchor, bool aBackward);
Accessible* mRoot;
AccessibleOrProxy mRoot;
};
/**
@ -91,12 +93,20 @@ class PivotRoleRule final : public PivotRule {
public:
explicit PivotRoleRule(role aRole);
virtual uint16_t Match(Accessible* aAccessible) override;
virtual uint16_t Match(const AccessibleOrProxy& aAccOrProxy) override;
private:
role mRole;
};
/**
* This rule matches all accessibles.
*/
class PivotMatchAllRule final : public PivotRule {
public:
virtual uint16_t Match(const AccessibleOrProxy& aAccOrProxy) override;
};
} // namespace a11y
} // namespace mozilla

Просмотреть файл

@ -27,7 +27,7 @@ class RuleCache : public PivotRule {
: mRule(aRule), mPreFilter{0} {}
~RuleCache() {}
virtual uint16_t Match(Accessible* aAccessible) override;
virtual uint16_t Match(const AccessibleOrProxy& aAccOrProxy) override;
private:
nsCOMPtr<nsIAccessibleTraversalRule> mRule;
@ -204,11 +204,17 @@ nsAccessiblePivot::MoveNext(nsIAccessibleTraversalRule* aRule,
Pivot pivot(GetActiveRoot());
RuleCache rule(aRule);
if (Accessible* newPos =
pivot.Next(anchor, rule, (aArgc > 1) ? aIncludeStart : false)) {
*aResult = MovePivotInternal(newPos, nsIAccessiblePivot::REASON_NEXT,
AccessibleOrProxy wrappedAnchor = AccessibleOrProxy(anchor);
AccessibleOrProxy newPos =
pivot.Next(wrappedAnchor, rule, (aArgc > 1) ? aIncludeStart : false);
if (!newPos.IsNull() && newPos.IsAccessible()) {
*aResult = MovePivotInternal(newPos.AsAccessible(),
nsIAccessiblePivot::REASON_NEXT,
(aArgc > 2) ? aIsFromUserInput : true);
} else if (newPos.IsProxy()) {
// we shouldn't ever end up with a proxy here, but if we do for some
// reason something is wrong. we should still return OK if we're null
return NS_ERROR_FAILURE;
}
return NS_OK;
@ -232,11 +238,17 @@ nsAccessiblePivot::MovePrevious(nsIAccessibleTraversalRule* aRule,
Pivot pivot(GetActiveRoot());
RuleCache rule(aRule);
if (Accessible* newPos =
pivot.Prev(anchor, rule, (aArgc > 1) ? aIncludeStart : false)) {
*aResult = MovePivotInternal(newPos, nsIAccessiblePivot::REASON_PREV,
AccessibleOrProxy wrappedAnchor = AccessibleOrProxy(anchor);
AccessibleOrProxy newPos =
pivot.Prev(wrappedAnchor, rule, (aArgc > 1) ? aIncludeStart : false);
if (!newPos.IsNull() && newPos.IsAccessible()) {
*aResult = MovePivotInternal(newPos.AsAccessible(),
nsIAccessiblePivot::REASON_PREV,
(aArgc > 2) ? aIsFromUserInput : true);
} else if (newPos.IsProxy()) {
// we shouldn't ever end up with a proxy here, but if we do for some
// reason something is wrong. we should still return OK if we're null
return NS_ERROR_FAILURE;
}
return NS_OK;
@ -254,10 +266,15 @@ nsAccessiblePivot::MoveFirst(nsIAccessibleTraversalRule* aRule,
Pivot pivot(GetActiveRoot());
RuleCache rule(aRule);
if (Accessible* newPos = pivot.First(rule)) {
*aResult = MovePivotInternal(newPos, nsIAccessiblePivot::REASON_FIRST,
AccessibleOrProxy newPos = pivot.First(rule);
if (!newPos.IsNull() && newPos.IsAccessible()) {
*aResult = MovePivotInternal(newPos.AsAccessible(),
nsIAccessiblePivot::REASON_FIRST,
(aArgc > 0) ? aIsFromUserInput : true);
} else if (newPos.IsProxy()) {
// we shouldn't ever end up with a proxy here, but if we do for some
// reason something is wrong. we should still return OK if we're null
return NS_ERROR_FAILURE;
}
return NS_OK;
@ -275,10 +292,15 @@ nsAccessiblePivot::MoveLast(nsIAccessibleTraversalRule* aRule,
Pivot pivot(root);
RuleCache rule(aRule);
if (Accessible* newPos = pivot.Last(rule)) {
*aResult = MovePivotInternal(newPos, nsIAccessiblePivot::REASON_LAST,
AccessibleOrProxy newPos = pivot.Last(rule);
if (!newPos.IsNull() && newPos.IsAccessible()) {
*aResult = MovePivotInternal(newPos.AsAccessible(),
nsIAccessiblePivot::REASON_LAST,
(aArgc > 0) ? aIsFromUserInput : true);
} else if (newPos.IsProxy()) {
// we shouldn't ever end up with a proxy here, but if we do for some
// reason something is wrong. we should still return OK if we're null
return NS_ERROR_FAILURE;
}
return NS_OK;
@ -295,8 +317,8 @@ nsAccessiblePivot::MoveNextByText(TextBoundaryType aBoundary,
Pivot pivot(GetActiveRoot());
int32_t newStart = mStartOffset, newEnd = mEndOffset;
if (Accessible* newPos =
pivot.NextText(mPosition, &newStart, &newEnd, aBoundary)) {
Accessible* newPos = pivot.NextText(mPosition, &newStart, &newEnd, aBoundary);
if (newPos) {
*aResult = true;
int32_t oldStart = mStartOffset, oldEnd = mEndOffset;
Accessible* oldPos = mPosition;
@ -322,8 +344,8 @@ nsAccessiblePivot::MovePreviousByText(TextBoundaryType aBoundary,
Pivot pivot(GetActiveRoot());
int32_t newStart = mStartOffset, newEnd = mEndOffset;
if (Accessible* newPos =
pivot.PrevText(mPosition, &newStart, &newEnd, aBoundary)) {
Accessible* newPos = pivot.PrevText(mPosition, &newStart, &newEnd, aBoundary);
if (newPos) {
*aResult = true;
int32_t oldStart = mStartOffset, oldEnd = mEndOffset;
Accessible* oldPos = mPosition;
@ -354,10 +376,16 @@ nsAccessiblePivot::MoveToPoint(nsIAccessibleTraversalRule* aRule, int32_t aX,
RuleCache rule(aRule);
Pivot pivot(root);
Accessible* newPos = pivot.AtPoint(aX, aY, rule);
if (newPos || !aIgnoreNoMatch) {
*aResult = MovePivotInternal(newPos, nsIAccessiblePivot::REASON_POINT,
AccessibleOrProxy newPos = pivot.AtPoint(aX, aY, rule);
if ((!newPos.IsNull() && newPos.IsAccessible()) ||
!aIgnoreNoMatch) { // TODO does this need a proxy check?
*aResult = MovePivotInternal(newPos.AsAccessible(),
nsIAccessiblePivot::REASON_POINT,
(aArgc > 0) ? aIsFromUserInput : true);
} else if (newPos.IsProxy()) {
// we shouldn't ever end up with a proxy here, but if we do for some
// reason something is wrong. we should still return OK if we're null
return NS_ERROR_FAILURE;
}
return NS_OK;
@ -427,7 +455,7 @@ bool nsAccessiblePivot::NotifyOfPivotChange(Accessible* aOldPosition,
return true;
}
uint16_t RuleCache::Match(Accessible* aAccessible) {
uint16_t RuleCache::Match(const AccessibleOrProxy& aAccOrProxy) {
uint16_t result = nsIAccessibleTraversalRule::FILTER_IGNORE;
if (!mAcceptRoles) {
@ -439,10 +467,15 @@ uint16_t RuleCache::Match(Accessible* aAccessible) {
}
if (mPreFilter) {
uint64_t state = aAccessible->State();
uint64_t state;
if (aAccOrProxy.IsAccessible()) {
state = aAccOrProxy.AsAccessible()->State();
} else {
state = aAccOrProxy.AsProxy()->State();
}
if ((nsIAccessibleTraversalRule::PREFILTER_PLATFORM_PRUNED & mPreFilter) &&
nsAccUtils::MustPrune(aAccessible)) {
nsAccUtils::MustPrune(aAccOrProxy)) {
result |= nsIAccessibleTraversalRule::FILTER_IGNORE_SUBTREE;
}
@ -458,9 +491,10 @@ uint16_t RuleCache::Match(Accessible* aAccessible) {
!(state & states::FOCUSABLE))
return result;
if ((nsIAccessibleTraversalRule::PREFILTER_TRANSPARENT & mPreFilter) &&
if (aAccOrProxy.IsAccessible() &&
(nsIAccessibleTraversalRule::PREFILTER_TRANSPARENT & mPreFilter) &&
!(state & states::OPAQUE1)) {
nsIFrame* frame = aAccessible->GetFrame();
nsIFrame* frame = aAccOrProxy.AsAccessible()->GetFrame();
if (frame->StyleEffects()->mOpacity == 0.0f) {
return result | nsIAccessibleTraversalRule::FILTER_IGNORE_SUBTREE;
}
@ -468,7 +502,7 @@ uint16_t RuleCache::Match(Accessible* aAccessible) {
}
if (mAcceptRoles->Length() > 0) {
uint32_t accessibleRole = aAccessible->Role();
uint32_t accessibleRole = aAccOrProxy.Role();
bool matchesRole = false;
for (uint32_t idx = 0; idx < mAcceptRoles->Length(); idx++) {
matchesRole = mAcceptRoles->ElementAt(idx) == accessibleRole;
@ -481,7 +515,7 @@ uint16_t RuleCache::Match(Accessible* aAccessible) {
}
uint16_t matchResult = nsIAccessibleTraversalRule::FILTER_IGNORE;
DebugOnly<nsresult> rv = mRule->Match(ToXPC(aAccessible), &matchResult);
DebugOnly<nsresult> rv = mRule->Match(ToXPC(aAccOrProxy), &matchResult);
MOZ_ASSERT(NS_SUCCEEDED(rv));
return result | matchResult;

Просмотреть файл

@ -1718,9 +1718,14 @@ Relation Accessible::RelationByType(RelationType aType) const {
* was called from, which is expected. */
Pivot p = Pivot(currParent);
PivotRoleRule rule(roles::RADIOBUTTON);
Accessible* match = currParent;
while ((match = p.Next(match, rule))) {
rel.AppendTarget(match);
AccessibleOrProxy wrappedParent = AccessibleOrProxy(currParent);
AccessibleOrProxy match = p.Next(wrappedParent, rule);
while (!match.IsNull()) {
MOZ_ASSERT(
!match.IsProxy(),
"We shouldn't find any proxy's while building our relation!");
rel.AppendTarget(match.AsAccessible());
match = p.Next(match, rule);
}
}