Bug 1765430 - P3: Refactor Android Pivot methods. r=Jamie

This creates a clearer distinction between local pivots and remote
pivots. The former happens in the parent process and the latter happens
in the remote content process.

Differential Revision: https://phabricator.services.mozilla.com/D144482
This commit is contained in:
Eitan Isaacson 2022-04-27 22:44:45 +00:00
Родитель f45be3470b
Коммит c9311969b2
13 изменённых файлов: 78 добавлений и 62 удалений

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

@ -283,38 +283,37 @@ bool AccessibleWrap::GetSelectionBounds(int32_t* aStartOffset,
return false;
}
Accessible* AccessibleWrap::DoPivot(Accessible* aAccessible,
int32_t aGranularity, bool aForward,
bool aInclusive) {
a11y::Pivot pivot(nullptr);
// Depending on the start accessible, the pivot rule will either traverse
// local or remote accessibles exclusively.
TraversalRule rule(aGranularity, aAccessible->IsLocal());
Accessible* result = aForward ? pivot.Next(aAccessible, rule, aInclusive)
: pivot.Prev(aAccessible, rule, aInclusive);
if (result && (result != aAccessible || aInclusive)) {
return result;
}
return nullptr;
}
bool AccessibleWrap::PivotTo(int32_t aGranularity, bool aForward,
bool aInclusive) {
a11y::Pivot pivot(RootAccessible());
TraversalRule rule(aGranularity);
Accessible* current = IsProxy() ? Proxy() : static_cast<Accessible*>(this);
Accessible* result = aForward ? pivot.Next(current, rule, aInclusive)
: pivot.Prev(current, rule, aInclusive);
if (result && (result != current || aInclusive)) {
RefPtr<AccessibleWrap> newPosition =
result->IsRemote() ? WrapperFor(result->AsRemote())
: static_cast<AccessibleWrap*>(result->AsLocal());
if (IPCAccessibilityActive()) {
// We are in the child process. Dispatch a virtual cursor
// change event that will be turned into an android
// accessibility focused changed event in the parent.
PivotMoveReason reason = aForward ? nsIAccessiblePivot::REASON_NEXT
: nsIAccessiblePivot::REASON_PREV;
LocalAccessible* localResult = result->AsLocal();
MOZ_ASSERT(localResult);
RefPtr<AccEvent> event = new AccVCChangeEvent(
localResult->Document(), this, -1, -1, localResult, -1, -1, reason,
nsIAccessiblePivot::NO_BOUNDARY, eFromUserInput);
nsEventShell::FireEvent(event);
} else {
// We are in the parent process. Dispatch an accessibility focused
// event directly.
RefPtr<SessionAccessibility> sessionAcc =
SessionAccessibility::GetInstanceFor(result);
sessionAcc->SendAccessibilityFocusedEvent(newPosition);
}
Accessible* result = DoPivot(this, aGranularity, aForward, aInclusive);
if (result) {
MOZ_ASSERT(result->IsLocal());
// Dispatch a virtual cursor change event that will be turned into an
// android accessibility focused changed event in the parent.
PivotMoveReason reason = aForward ? nsIAccessiblePivot::REASON_NEXT
: nsIAccessiblePivot::REASON_PREV;
LocalAccessible* localResult = result->AsLocal();
RefPtr<AccEvent> event = new AccVCChangeEvent(
localResult->Document(), this, -1, -1, localResult, -1, -1, reason,
nsIAccessiblePivot::NO_BOUNDARY, eFromUserInput);
nsEventShell::FireEvent(event);
return true;
}
@ -324,7 +323,7 @@ bool AccessibleWrap::PivotTo(int32_t aGranularity, bool aForward,
void AccessibleWrap::ExploreByTouch(float aX, float aY) {
a11y::Pivot pivot(RootAccessible());
ExploreByTouchRule rule;
TraversalRule rule;
Accessible* maybeResult = pivot.AtPoint(aX, aY, rule);
LocalAccessible* result = maybeResult ? maybeResult->AsLocal() : nullptr;

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

@ -83,6 +83,9 @@ class AccessibleWrap : public LocalAccessible {
static void SetVirtualViewID(Accessible* aAccessible, int32_t aVirtualViewID);
static Accessible* DoPivot(Accessible* aAccessible, int32_t aGranularity,
bool aForward, bool aInclusive);
protected:
int32_t mID;

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

@ -157,7 +157,8 @@ void DocAccessibleWrap::CacheViewportCallback(nsITimer* aTimer,
if (docAcc->mCachePivotBoundaries) {
a11y::Pivot pivot(docAcc);
TraversalRule rule(java::SessionAccessibility::HTML_GRANULARITY_DEFAULT);
TraversalRule rule(java::SessionAccessibility::HTML_GRANULARITY_DEFAULT,
true);
Accessible* maybeFirst = pivot.First(rule);
Accessible* maybeLast = pivot.Last(rule);
LocalAccessible* first = maybeFirst ? maybeFirst->AsLocal() : nullptr;

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

@ -109,7 +109,7 @@ bool RemoteAccessibleWrap::PivotTo(int32_t aGranularity, bool aForward,
return AccessibleWrap::PivotTo(aGranularity, aForward, aInclusive);
}
Unused << Proxy()->Document()->GetPlatformExtension()->SendPivot(
Unused << Proxy()->Document()->GetPlatformExtension()->SendPivotTo(
Proxy()->ID(), aGranularity, aForward, aInclusive);
return true;

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

@ -126,11 +126,24 @@ bool SessionAccessibility::CachedPivot(int32_t aID, int32_t aGranularity,
bool ret = false;
nsAppShell::SyncRunEvent(
[this, self, aID, aGranularity, aForward, aInclusive, &ret] {
if (AccessibleWrap* acc = GetAccessibleByID(aID)) {
ret = acc->PivotTo(aGranularity, aForward, aInclusive);
if (Accessible* acc = GetAccessibleByID(aID)) {
if (acc->AsLocal()->IsProxy()) {
// XXX: Will be removed with RemoteAccessibleWrap
acc = acc->AsLocal()->Proxy();
}
Accessible* result =
AccessibleWrap::DoPivot(acc, aGranularity, aForward, aInclusive);
if (result) {
ret = true;
int32_t virtualViewID = AccessibleWrap::GetVirtualViewID(result);
nsAppShell::PostEvent([this, self, virtualViewID] {
if (AccessibleWrap* acc = GetAccessibleByID(virtualViewID)) {
SendAccessibilityFocusedEvent(acc);
}
});
}
}
});
return ret;
}
@ -236,7 +249,8 @@ void SessionAccessibility::SendAccessibilityFocusedEvent(
mSessionAccessibility->SendEvent(
java::sdk::AccessibilityEvent::TYPE_VIEW_ACCESSIBILITY_FOCUSED,
aAccessible->VirtualViewID(), aAccessible->AndroidClass(), nullptr);
aAccessible->ScrollTo(nsIAccessibleScrollType::SCROLL_TYPE_ANYWHERE);
RefPtr<AccessibleWrap> acc = aAccessible;
acc->ScrollTo(nsIAccessibleScrollType::SCROLL_TYPE_ANYWHERE);
}
void SessionAccessibility::SendHoverEnterEvent(AccessibleWrap* aAccessible) {

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

@ -70,7 +70,7 @@ class SessionAccessibility final
void SendScrollingEvent(AccessibleWrap* aAccessible, int32_t aScrollX,
int32_t aScrollY, int32_t aMaxScrollX,
int32_t aMaxScrollY);
MOZ_CAN_RUN_SCRIPT
MOZ_CAN_RUN_SCRIPT_BOUNDARY
void SendAccessibilityFocusedEvent(AccessibleWrap* aAccessible);
void SendHoverEnterEvent(AccessibleWrap* aAccessible);
void SendTextSelectionChangedEvent(AccessibleWrap* aAccessible,

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

@ -19,14 +19,28 @@ using namespace mozilla;
using namespace mozilla::a11y;
TraversalRule::TraversalRule()
: TraversalRule(java::SessionAccessibility::HTML_GRANULARITY_DEFAULT) {}
: TraversalRule(java::SessionAccessibility::HTML_GRANULARITY_DEFAULT,
true) {}
TraversalRule::TraversalRule(int32_t aGranularity)
: mGranularity(aGranularity) {}
TraversalRule::TraversalRule(int32_t aGranularity, bool aIsLocal)
: mGranularity(aGranularity), mIsLocal(aIsLocal) {}
uint16_t TraversalRule::Match(Accessible* aAcc) {
MOZ_ASSERT(aAcc);
if (mIsLocal && aAcc->IsRemote()) {
// If we encounter a remote accessible in a local rule, we should
// ignore the subtree because we won't encounter anymore local accessibles
// in it.
return nsIAccessibleTraversalRule::FILTER_IGNORE |
nsIAccessibleTraversalRule::FILTER_IGNORE_SUBTREE;
} else if (!mIsLocal && aAcc->IsLocal()) {
// If we encounter a local accessible in a remote rule we are likely
// traversing backwards/upwards, we don't ignore its subtree because it is
// likely the outer doc root of the remote tree.
return nsIAccessibleTraversalRule::FILTER_IGNORE;
}
uint16_t result = nsIAccessibleTraversalRule::FILTER_IGNORE;
if (nsAccUtils::MustPrune(aAcc)) {
@ -281,14 +295,3 @@ uint16_t TraversalRule::DefaultMatch(Accessible* aAccessible) {
return nsIAccessibleTraversalRule::FILTER_IGNORE;
}
uint16_t ExploreByTouchRule::Match(Accessible* aAcc) {
if (aAcc->IsRemote()) {
// Explore by touch happens in the local process and should
// not drill down into remote frames.
return nsIAccessibleTraversalRule::FILTER_IGNORE |
nsIAccessibleTraversalRule::FILTER_IGNORE_SUBTREE;
}
return TraversalRule::Match(aAcc);
}

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

@ -20,7 +20,7 @@ class Accessible;
class TraversalRule : public PivotRule {
public:
TraversalRule();
explicit TraversalRule(int32_t aGranularity);
explicit TraversalRule(int32_t aGranularity, bool aIsLocal);
~TraversalRule() = default;
@ -48,10 +48,8 @@ class TraversalRule : public PivotRule {
uint16_t LandmarkMatch(Accessible* aAccessible);
int32_t mGranularity;
};
class ExploreByTouchRule final : public TraversalRule {
virtual uint16_t Match(Accessible* aAcc) override;
bool mIsLocal;
};
} // namespace a11y

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

@ -119,7 +119,6 @@ void ProxySelectionEvent(RemoteAccessible* aTarget, RemoteAccessible* aWidget,
uint32_t aType);
#if defined(ANDROID)
MOZ_CAN_RUN_SCRIPT
void ProxyVirtualCursorChangeEvent(RemoteAccessible* aTarget,
RemoteAccessible* aOldPosition,
int32_t aOldStartOffset,

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

@ -129,7 +129,6 @@ class DocAccessibleParent : public RemoteAccessible,
const uint64_t& aID, const uint64_t& aWidgetID,
const uint32_t& aType) override;
MOZ_CAN_RUN_SCRIPT_BOUNDARY
virtual mozilla::ipc::IPCResult RecvVirtualCursorChangeEvent(
const uint64_t& aID, const uint64_t& aOldPositionID,
const int32_t& aOldStartOffset, const int32_t& aOldEndOffset,

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

@ -12,7 +12,7 @@
namespace mozilla {
namespace a11y {
mozilla::ipc::IPCResult DocAccessiblePlatformExtChild::RecvPivot(
mozilla::ipc::IPCResult DocAccessiblePlatformExtChild::RecvPivotTo(
uint64_t aID, int32_t aGranularity, bool aForward, bool aInclusive) {
if (auto acc = IdToAccessibleWrap(aID)) {
acc->PivotTo(aGranularity, aForward, aInclusive);

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

@ -16,8 +16,8 @@ class DocAccessibleChild;
class DocAccessiblePlatformExtChild : public PDocAccessiblePlatformExtChild {
public:
mozilla::ipc::IPCResult RecvPivot(uint64_t aID, int32_t aGranularity,
bool aForward, bool aInclusive);
mozilla::ipc::IPCResult RecvPivotTo(uint64_t aID, int32_t aGranularity,
bool aForward, bool aInclusive);
mozilla::ipc::IPCResult RecvNavigateText(uint64_t aID, int32_t aGranularity,
int32_t aStartOffset,

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

@ -16,7 +16,7 @@ protocol PDocAccessiblePlatformExt {
child:
async __delete__();
async Pivot(uint64_t aID, int32_t aGranularity, bool aForward, bool aInclusive);
async PivotTo(uint64_t aID, int32_t aGranularity, bool aForward, bool aInclusive);
async NavigateText(uint64_t aID, int32_t aGranularity, int32_t aStartOffset, int32_t aEndOffset, bool aForward, bool aSelect);