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; return false;
} }
void AccessibleWrap::ExploreByTouch(float aX, float aY) { Accessible* AccessibleWrap::ExploreByTouch(Accessible* aAccessible, float aX,
a11y::Pivot pivot(RootAccessible()); float aY) {
TraversalRule rule; Accessible* root;
if (LocalAccessible* local = aAccessible->AsLocal()) {
Accessible* maybeResult = pivot.AtPoint(aX, aY, rule); root = local->RootAccessible();
LocalAccessible* result = maybeResult ? maybeResult->AsLocal() : nullptr; } else {
// If this is a RemoteAccessible, provide the top level
if (result && result != this) { // remote doc as the pivot root for thread safety reasons.
RefPtr<AccEvent> event = DocAccessibleParent* doc = aAccessible->AsRemote()->Document();
new AccVCChangeEvent(result->Document(), this, result, while (doc && !doc->IsTopLevel()) {
nsIAccessiblePivot::REASON_POINT, eFromUserInput); doc = doc->ParentDoc();
nsEventShell::FireEvent(event); }
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) { static TextLeafPoint ToTextLeafPoint(Accessible* aAccessible, int32_t aOffset) {

View File

@@ -30,7 +30,8 @@ class AccessibleWrap : public LocalAccessible {
MOZ_CAN_RUN_SCRIPT_BOUNDARY MOZ_CAN_RUN_SCRIPT_BOUNDARY
virtual bool PivotTo(int32_t aGranularity, bool aForward, bool aInclusive); 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); static uint32_t GetFlags(role aRole, uint64_t aState, uint8_t aActionCount);

View File

@@ -186,11 +186,7 @@ void a11y::PlatformVirtualCursorChangeEvent(Accessible* aTarget,
return; return;
} }
if (aReason == nsIAccessiblePivot::REASON_POINT) { sessionAcc->SendAccessibilityFocusedEvent(aNewPosition);
sessionAcc->SendHoverEnterEvent(aNewPosition);
} else {
sessionAcc->SendAccessibilityFocusedEvent(aNewPosition);
}
} }
void a11y::PlatformScrollingEvent(Accessible* aTarget, uint32_t aEventType, 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 { namespace a11y {
/** using RootAccessibleWrap = RootAccessible;
* 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;
};
} // namespace a11y } // namespace a11y
} // namespace mozilla } // namespace mozilla

View File

@@ -12,8 +12,8 @@
#include "nsThreadUtils.h" #include "nsThreadUtils.h"
#include "AccAttributes.h" #include "AccAttributes.h"
#include "AccessibilityEvent.h" #include "AccessibilityEvent.h"
#include "DocAccessibleWrap.h"
#include "JavaBuiltins.h" #include "JavaBuiltins.h"
#include "RootAccessibleWrap.h"
#include "nsAccessibilityService.h" #include "nsAccessibilityService.h"
#include "nsAccUtils.h" #include "nsAccUtils.h"
#include "nsViewManager.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) { void SessionAccessibility::ExploreByTouch(int32_t aID, float aX, float aY) {
auto gvAccessor(mWindow.Access()); MOZ_ASSERT(AndroidBridge::IsJavaUiThread());
if (gvAccessor) { MonitorAutoLock mal(nsAccessibilityService::GetAndroidMonitor());
if (nsWindow* gkWindow = gvAccessor->GetNsWindow()) { RefPtr<SessionAccessibility> self(this);
WidgetMouseEvent hittest(true, eMouseExploreByTouch, gkWindow, if (Accessible* origin = GetAccessibleByID(aID)) {
WidgetMouseEvent::eReal); if (origin->IsLocal()) {
hittest.mRefPoint = LayoutDeviceIntPoint::Floor(aX, aY); nsAppShell::PostEvent([this, self, aID, aX, aY] {
hittest.mInputSource = dom::MouseEvent_Binding::MOZ_SOURCE_TOUCH; MonitorAutoLock mal(nsAccessibilityService::GetAndroidMonitor());
hittest.mFlags.mOnlyChromeDispatch = true; if (Accessible* origin = GetAccessibleByID(aID)) {
gkWindow->DispatchInputEvent(&hittest); 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 "nsAppShell.h"
#include "nsThreadUtils.h" #include "nsThreadUtils.h"
#include "nsWindow.h" #include "nsWindow.h"
#include "AccessibleWrap.h"
namespace mozilla { namespace mozilla {
namespace a11y { namespace a11y {
class AccessibleWrap;
class AccAttributes;
class Accessible; class Accessible;
class RemoteAccessible;
class RootAccessibleWrap;
class BatchData;
class SessionAccessibility final class SessionAccessibility final
: public java::SessionAccessibility::NativeProvider::Natives< : public java::SessionAccessibility::NativeProvider::Natives<

View File

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

View File

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