Skip to content
This repository was archived by the owner on Feb 25, 2025. It is now read-only.
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -51,11 +51,10 @@ class AccessibilityViewEmbedder {
// Maps a platform view and originId to a corresponding flutterID.
private final Map<ViewAndId, Integer> originToFlutterId;

// Maps the flutterId of an accessibility node to the screen bounds of
// the root semantic node for the embedded view.
// Maps an embedded view to it's screen bounds.
// This is used to translate the coordinates of the accessibility node subtree to the main display's coordinate
// system.
private final SparseArray<Rect> flutterIdToDisplayBounds;
private final Map<View, Rect> embeddedViewToDisplayBounds;

private int nextFlutterId;

Expand All @@ -64,8 +63,8 @@ class AccessibilityViewEmbedder {
flutterIdToOrigin = new SparseArray<>();
this.rootAccessibilityView = rootAccessibiiltyView;
nextFlutterId = firstVirtualNodeId;
flutterIdToDisplayBounds = new SparseArray<>();
originToFlutterId = new HashMap<>();
embeddedViewToDisplayBounds = new HashMap<>();
}

/**
Expand All @@ -80,10 +79,9 @@ public AccessibilityNodeInfo getRootNode(@NonNull View embeddedView, int flutter
if (originPackedId == null) {
return null;
}
embeddedViewToDisplayBounds.put(embeddedView, displayBounds);
int originId = ReflectionAccessors.getVirtualNodeId(originPackedId);
flutterIdToOrigin.put(flutterId, new ViewAndId(embeddedView, originId));
flutterIdToDisplayBounds.put(flutterId, displayBounds);
originToFlutterId.put(new ViewAndId(embeddedView, originId), flutterId);
cacheVirtualIdMappings(embeddedView, originId, flutterId);
return convertToFlutterNode(originNode, flutterId, embeddedView);
}

Expand All @@ -96,6 +94,13 @@ public AccessibilityNodeInfo createAccessibilityNodeInfo(int flutterId) {
if (origin == null) {
return null;
}
if (!embeddedViewToDisplayBounds.containsKey(origin.view)) {
// This might happen if the embedded view is sending accessibility event before the first Flutter semantics
// tree was sent to the accessibility bridge. In this case we don't return a node as we do not know the
// bounds yet.
// https://github.com/flutter/flutter/issues/30068
return null;
}
AccessibilityNodeProvider provider = origin.view.getAccessibilityNodeProvider();
if (provider == null) {
// The provider is null for views that don't have a virtual accessibility tree.
Expand Down Expand Up @@ -127,7 +132,7 @@ private AccessibilityNodeInfo convertToFlutterNode(
result.setSource(rootAccessibilityView, flutterId);
result.setClassName(originNode.getClassName());

Rect displayBounds = flutterIdToDisplayBounds.get(flutterId);
Rect displayBounds = embeddedViewToDisplayBounds.get(embeddedView);

copyAccessibilityFields(originNode, result);
setFlutterNodesTranslateBounds(originNode, displayBounds, result);
Expand Down Expand Up @@ -172,14 +177,21 @@ private void addChildrenToFlutterNode(
childFlutterId = originToFlutterId.get(origin);
} else {
childFlutterId = nextFlutterId++;
originToFlutterId.put(origin, childFlutterId);
flutterIdToOrigin.put(childFlutterId, origin);
flutterIdToDisplayBounds.put(childFlutterId, displayBounds);
cacheVirtualIdMappings(embeddedView, originId, childFlutterId);
}
resultNode.addChild(rootAccessibilityView, childFlutterId);
}
}

// Caches a bidirectional mapping of (embeddedView, originId)<-->flutterId.
// Where originId is a virtual node ID in the embeddedView's tree, and flutterId is the ID
// of the corresponding node in the Flutter virtual accessibility nodes tree.
private void cacheVirtualIdMappings(@NonNull View embeddedView, int originId, int flutterId) {
ViewAndId origin = new ViewAndId(embeddedView, originId);
originToFlutterId.put(origin, flutterId);
flutterIdToOrigin.put(flutterId, origin);
}

private void setFlutterNodesTranslateBounds(
@NonNull AccessibilityNodeInfo originNode,
@NonNull Rect displayBounds,
Expand Down Expand Up @@ -265,7 +277,8 @@ public boolean requestSendAccessibilityEvent(
int originVirtualId = ReflectionAccessors.getVirtualNodeId(originPackedId);
Integer flutterId = originToFlutterId.get(new ViewAndId(embeddedView, originVirtualId));
if (flutterId == null) {
return false;
flutterId = nextFlutterId++;
cacheVirtualIdMappings(embeddedView, originVirtualId, flutterId);
}
translatedEvent.setSource(rootAccessibilityView, flutterId);
translatedEvent.setClassName(event.getClassName());
Expand Down Expand Up @@ -333,7 +346,7 @@ public boolean onAccessibilityHoverEvent(int rootFlutterId, @NonNull MotionEvent
if (origin == null) {
return false;
}
Rect displayBounds = flutterIdToDisplayBounds.get(rootFlutterId);
Rect displayBounds = embeddedViewToDisplayBounds.get(origin.view);
int pointerCount = event.getPointerCount();
MotionEvent.PointerProperties[] pointerProperties = new MotionEvent.PointerProperties[pointerCount];
MotionEvent.PointerCoords[] pointerCoords = new MotionEvent.PointerCoords[pointerCount];
Expand Down