Bug 1822004: On Android, use RemoteAccessible (CtW) hit testing instead of a DOM event. r=eeejay

This unifies hit testing across all platforms.
It also removes one of the few remaining uses of virtual cursor change events.

Differential Revision: https://phabricator.services.mozilla.com/D192641
This commit is contained in:
James Teh
2023-11-28 07:37:30 +00:00
parent 37d8891ddf
commit 32d424ea16
9 changed files with 51 additions and 121 deletions

View File

@@ -173,19 +173,29 @@ bool AccessibleWrap::PivotTo(int32_t aGranularity, bool aForward,
return false;
}
void AccessibleWrap::ExploreByTouch(float aX, float aY) {
a11y::Pivot pivot(RootAccessible());
TraversalRule rule;
Accessible* maybeResult = pivot.AtPoint(aX, aY, rule);
LocalAccessible* result = maybeResult ? maybeResult->AsLocal() : nullptr;
if (result && result != this) {
RefPtr<AccEvent> event =
new AccVCChangeEvent(result->Document(), this, result,
nsIAccessiblePivot::REASON_POINT, eFromUserInput);
nsEventShell::FireEvent(event);
Accessible* AccessibleWrap::ExploreByTouch(Accessible* aAccessible, float aX,
float aY) {
Accessible* root;
if (LocalAccessible* local = aAccessible->AsLocal()) {
root = local->RootAccessible();
} else {
// If this is a RemoteAccessible, provide the top level
// remote doc as the pivot root for thread safety reasons.
DocAccessibleParent* doc = aAccessible->AsRemote()->Document();
while (doc && !doc->IsTopLevel()) {
doc = doc->ParentDoc();
}
MOZ_ASSERT(doc, "Failed to get top level DocAccessibleParent");
root = doc;
}
a11y::Pivot pivot(root);
TraversalRule rule(java::SessionAccessibility::HTML_GRANULARITY_DEFAULT,
aAccessible->IsLocal());
Accessible* result = pivot.AtPoint(aX, aY, rule);
if (result == aAccessible) {
return nullptr;
}
return result;
}
static TextLeafPoint ToTextLeafPoint(Accessible* aAccessible, int32_t aOffset) {

View File

@@ -30,7 +30,8 @@ class AccessibleWrap : public LocalAccessible {
MOZ_CAN_RUN_SCRIPT_BOUNDARY
virtual bool PivotTo(int32_t aGranularity, bool aForward, bool aInclusive);
void ExploreByTouch(float aX, float aY);
static Accessible* ExploreByTouch(Accessible* aAccessible, float aX,
float aY);
static uint32_t GetFlags(role aRole, uint64_t aState, uint8_t aActionCount);

View File

@@ -186,11 +186,7 @@ void a11y::PlatformVirtualCursorChangeEvent(Accessible* aTarget,
return;
}
if (aReason == nsIAccessiblePivot::REASON_POINT) {
sessionAcc->SendHoverEnterEvent(aNewPosition);
} else {
sessionAcc->SendAccessibilityFocusedEvent(aNewPosition);
}
}
void a11y::PlatformScrollingEvent(Accessible* aTarget, uint32_t aEventType,

View File

@@ -1,69 +0,0 @@
/* -*- Mode: c++; c-basic-offset: 2; tab-width: 20; indent-tabs-mode: nil; -*-
* 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 "RootAccessibleWrap.h"
#include "LocalAccessible-inl.h"
#include "DocAccessibleParent.h"
#include "DocAccessible-inl.h"
#include "SessionAccessibility.h"
#include "mozilla/PresShell.h"
#include "mozilla/dom/EventTarget.h"
#include "mozilla/dom/Event.h"
#include "mozilla/dom/MouseEvent.h"
using namespace mozilla;
using namespace mozilla::a11y;
using namespace mozilla::dom;
RootAccessibleWrap::RootAccessibleWrap(dom::Document* aDoc,
PresShell* aPresShell)
: RootAccessible(aDoc, aPresShell) {}
RootAccessibleWrap::~RootAccessibleWrap() {}
nsresult RootAccessibleWrap::AddEventListeners() {
nsPIDOMWindowOuter* window = mDocumentNode->GetWindow();
nsCOMPtr<EventTarget> nstarget = window ? window->GetParentTarget() : nullptr;
if (nstarget) {
nstarget->AddEventListener(u"MozMouseExploreByTouch"_ns, this, false, true);
}
return RootAccessible::AddEventListeners();
}
nsresult RootAccessibleWrap::RemoveEventListeners() {
nsPIDOMWindowOuter* window = mDocumentNode->GetWindow();
nsCOMPtr<EventTarget> nstarget = window ? window->GetParentTarget() : nullptr;
if (nstarget) {
nstarget->RemoveEventListener(u"MozMouseExploreByTouch"_ns, this, true);
}
return RootAccessible::RemoveEventListeners();
}
////////////////////////////////////////////////////////////////////////////////
// nsIDOMEventListener
NS_IMETHODIMP
RootAccessibleWrap::HandleEvent(Event* aDOMEvent) {
WidgetMouseEvent* widgetEvent = aDOMEvent->WidgetEventPtr()->AsMouseEvent();
if (widgetEvent && widgetEvent->mMessage == eMouseExploreByTouch) {
if (HasShutdown()) {
return NS_OK;
}
if (MouseEvent* mouseEvent = aDOMEvent->AsMouseEvent()) {
LayoutDeviceIntPoint point = mouseEvent->ScreenPointLayoutDevicePix();
ExploreByTouch(point.x, point.y);
}
return NS_OK;
}
return RootAccessible::HandleEvent(aDOMEvent);
}

View File

@@ -14,22 +14,7 @@ class PresShell;
namespace a11y {
/**
* Android specific functionality for the node at a root of the accessibility
* tree: see the RootAccessible superclass for further details.
*/
class RootAccessibleWrap : public RootAccessible {
public:
RootAccessibleWrap(dom::Document* aDocument, PresShell* aPresShell);
virtual ~RootAccessibleWrap();
// nsIDOMEventListener
NS_DECL_NSIDOMEVENTLISTENER
protected:
virtual nsresult AddEventListeners() override;
virtual nsresult RemoveEventListeners() override;
};
using RootAccessibleWrap = RootAccessible;
} // namespace a11y
} // namespace mozilla

View File

@@ -12,8 +12,8 @@
#include "nsThreadUtils.h"
#include "AccAttributes.h"
#include "AccessibilityEvent.h"
#include "DocAccessibleWrap.h"
#include "JavaBuiltins.h"
#include "RootAccessibleWrap.h"
#include "nsAccessibilityService.h"
#include "nsAccUtils.h"
#include "nsViewManager.h"
@@ -192,15 +192,30 @@ bool SessionAccessibility::Pivot(int32_t aID, int32_t aGranularity,
}
void SessionAccessibility::ExploreByTouch(int32_t aID, float aX, float aY) {
auto gvAccessor(mWindow.Access());
if (gvAccessor) {
if (nsWindow* gkWindow = gvAccessor->GetNsWindow()) {
WidgetMouseEvent hittest(true, eMouseExploreByTouch, gkWindow,
WidgetMouseEvent::eReal);
hittest.mRefPoint = LayoutDeviceIntPoint::Floor(aX, aY);
hittest.mInputSource = dom::MouseEvent_Binding::MOZ_SOURCE_TOUCH;
hittest.mFlags.mOnlyChromeDispatch = true;
gkWindow->DispatchInputEvent(&hittest);
MOZ_ASSERT(AndroidBridge::IsJavaUiThread());
MonitorAutoLock mal(nsAccessibilityService::GetAndroidMonitor());
RefPtr<SessionAccessibility> self(this);
if (Accessible* origin = GetAccessibleByID(aID)) {
if (origin->IsLocal()) {
nsAppShell::PostEvent([this, self, aID, aX, aY] {
MonitorAutoLock mal(nsAccessibilityService::GetAndroidMonitor());
if (Accessible* origin = GetAccessibleByID(aID)) {
if (Accessible* result =
AccessibleWrap::ExploreByTouch(origin, aX, aY)) {
SendHoverEnterEvent(result);
}
}
});
} else {
if (Accessible* result = AccessibleWrap::ExploreByTouch(origin, aX, aY)) {
int32_t resultID = AccessibleWrap::GetVirtualViewID(result);
nsAppShell::PostEvent([this, self, resultID] {
MonitorAutoLock mal(nsAccessibilityService::GetAndroidMonitor());
if (Accessible* result = GetAccessibleByID(resultID)) {
SendHoverEnterEvent(result);
}
});
}
}
}
}

View File

@@ -11,17 +11,11 @@
#include "nsAppShell.h"
#include "nsThreadUtils.h"
#include "nsWindow.h"
#include "AccessibleWrap.h"
namespace mozilla {
namespace a11y {
class AccessibleWrap;
class AccAttributes;
class Accessible;
class RemoteAccessible;
class RootAccessibleWrap;
class BatchData;
class SessionAccessibility final
: public java::SessionAccessibility::NativeProvider::Natives<

View File

@@ -14,7 +14,6 @@ SOURCES += [
"AccessibleWrap.cpp",
"DocAccessibleWrap.cpp",
"Platform.cpp",
"RootAccessibleWrap.cpp",
"SessionAccessibility.cpp",
"TraversalRule.cpp",
]

View File

@@ -26,7 +26,6 @@ interface nsIAccessiblePivot : nsISupports
const PivotMoveReason REASON_PREV = 2;
const PivotMoveReason REASON_FIRST = 3;
const PivotMoveReason REASON_LAST = 4;
const PivotMoveReason REASON_POINT = 5;
/**
* Move pivot to next object, from current position or given anchor,