提交 cb789edc 编写于 作者: H Hixie

Make AccessibilityNodeInfos interactive.

This exposes the actions on AccessibilityNodeInfo nodes.
It also tries to make the code that handles reloads more correct.
上级 fcc26eef
......@@ -6,6 +6,7 @@ package org.domokit.sky.shell;
import android.graphics.Rect;
import android.opengl.Matrix;
import android.os.Bundle;
import android.view.View;
import android.view.accessibility.AccessibilityManager;
import android.view.accessibility.AccessibilityNodeInfo;
......@@ -26,10 +27,15 @@ public class FlutterSemanticsToAndroidAccessibilityBridge extends AccessibilityN
implements SemanticsListener {
private Map<Integer, PersistentAccessibilityNode> mTreeNodes;
private PlatformViewAndroid mOwner;
private SemanticsServer.Proxy mSemanticsServer;
FlutterSemanticsToAndroidAccessibilityBridge(PlatformViewAndroid view) {
mOwner = view;
FlutterSemanticsToAndroidAccessibilityBridge(PlatformViewAndroid owner, SemanticsServer.Proxy semanticsServer) {
assert owner != null;
assert semanticsServer != null;
mOwner = owner;
mTreeNodes = new HashMap<Integer, PersistentAccessibilityNode>();
mSemanticsServer = semanticsServer;
mSemanticsServer.addSemanticsListener(this);
}
@Override
......@@ -71,17 +77,39 @@ public class FlutterSemanticsToAndroidAccessibilityBridge extends AccessibilityN
}
result.setBoundsInScreen(bounds);
result.setVisibleToUser(true);
result.setEnabled(true); // TODO(ianh): Expose disabled subtrees
// TODO(ianh): Add support for interactivity:
// private boolean canBeTapped;
// private boolean canBeLongPressed;
// private boolean canBeScrolledHorizontally;
// private boolean canBeScrolledVertically;
if (node.canBeTapped) {
result.addAction(AccessibilityNodeInfo.ACTION_CLICK);
result.setClickable(true);
}
if (node.canBeLongPressed) {
result.addAction(AccessibilityNodeInfo.ACTION_LONG_CLICK);
result.setLongClickable(true);
}
if ((node.canBeScrolledHorizontally && !node.canBeScrolledVertically) ||
(!node.canBeScrolledHorizontally && node.canBeScrolledVertically)) {
result.addAction(AccessibilityNodeInfo.ACTION_SCROLL_FORWARD);
result.addAction(AccessibilityNodeInfo.ACTION_SCROLL_BACKWARD);
}
if (node.canBeScrolledHorizontally || node.canBeScrolledVertically) {
// TODO(ianh): Figure out how to enable panning. SDK v23
// has AccessibilityAction.ACTION_SCROLL_LEFT and company,
// but earlier versions do not. Right now we only forward
// scroll actions if it's unidirectional.
result.setScrollable(true);
}
result.setCheckable(node.hasCheckedState);
result.setChecked(node.isChecked);
result.setText(node.label);
// TODO(ianh): use setTraversalBefore/setTraversalAfter to set
// the relative order of the views. For each set of siblings,
// the views should be ordered top-to-bottom, tie-breaking
// left-to-right (right-to-left in rtl environments), height,
// width, and finally by list order.
for (PersistentAccessibilityNode child : node.children) {
result.addChild(mOwner, child.id);
}
......@@ -89,6 +117,48 @@ public class FlutterSemanticsToAndroidAccessibilityBridge extends AccessibilityN
return result;
}
@Override
public boolean performAction(int virtualViewId, int action, Bundle arguments) {
if (!mTreeNodes.containsKey(virtualViewId))
return false;
switch (action) {
case AccessibilityNodeInfo.ACTION_CLICK: {
mSemanticsServer.tap(virtualViewId);
return true;
}
case AccessibilityNodeInfo.ACTION_LONG_CLICK: {
mSemanticsServer.longPress(virtualViewId);
return true;
}
case AccessibilityNodeInfo.ACTION_SCROLL_BACKWARD: {
PersistentAccessibilityNode node = mTreeNodes.get(virtualViewId);
if (node.canBeScrolledHorizontally && !node.canBeScrolledVertically) {
// TODO(ianh): bidi support
mSemanticsServer.scrollLeft(virtualViewId);
} else if (node.canBeScrolledHorizontally && !node.canBeScrolledVertically) {
mSemanticsServer.scrollUp(virtualViewId);
} else {
return false;
}
return true;
}
case AccessibilityNodeInfo.ACTION_SCROLL_FORWARD: {
PersistentAccessibilityNode node = mTreeNodes.get(virtualViewId);
if (node.canBeScrolledHorizontally && !node.canBeScrolledVertically) {
// TODO(ianh): bidi support
mSemanticsServer.scrollRight(virtualViewId);
} else if (node.canBeScrolledHorizontally && !node.canBeScrolledVertically) {
mSemanticsServer.scrollDown(virtualViewId);
} else {
return false;
}
return true;
}
}
// TODO(ianh): Implement left/right/up/down scrolling
return false;
}
@Override
public void updateSemanticsTree(SemanticsNode[] nodes) {
for (SemanticsNode node : nodes) {
......@@ -114,8 +184,11 @@ public class FlutterSemanticsToAndroidAccessibilityBridge extends AccessibilityN
mTreeNodes.remove(node.id);
}
public void reset() {
public void reset(SemanticsServer.Proxy newSemanticsServer) {
mTreeNodes.clear();
mSemanticsServer.close();
mSemanticsServer = newSemanticsServer;
mSemanticsServer.addSemanticsListener(this);
}
private class PersistentAccessibilityNode {
......
......@@ -37,8 +37,6 @@ import org.chromium.mojom.pointer.PointerKind;
import org.chromium.mojom.pointer.PointerPacket;
import org.chromium.mojom.pointer.PointerType;
import org.chromium.mojom.raw_keyboard.RawKeyboardService;
import org.chromium.mojom.semantics.SemanticsListener;
import org.chromium.mojom.semantics.SemanticsNode;
import org.chromium.mojom.semantics.SemanticsServer;
import org.chromium.mojom.sky.ServicesData;
import org.chromium.mojom.sky.SkyEngine;
......@@ -298,6 +296,14 @@ public class PlatformViewAndroid extends SurfaceView
}
void runFromBundle(String path) {
if (mServiceProvider != null) {
mServiceProvider.close();
}
if (mDartServiceProvider != null) {
mDartServiceProvider.close();
}
Core core = CoreImpl.getInstance();
Pair<ServiceProvider.Proxy, InterfaceRequest<ServiceProvider>> serviceProvider =
ServiceProvider.MANAGER.getInterfaceRequest(core);
......@@ -348,35 +354,36 @@ public class PlatformViewAndroid extends SurfaceView
// TODO(ianh): else, actually discard the state for exploration
}
@Override
public AccessibilityNodeProvider getAccessibilityNodeProvider() {
ensureAccessibilityEnabled();
return mAccessibilityNodeProvider;
}
private FlutterSemanticsToAndroidAccessibilityBridge mAccessibilityNodeProvider;
private SemanticsServer.Proxy mSemanticsServer;
void ensureAccessibilityEnabled() {
if (mAccessibilityNodeProvider == null) {
mAccessibilityNodeProvider = new FlutterSemanticsToAndroidAccessibilityBridge(this);
Core core = CoreImpl.getInstance();
Pair<SemanticsServer.Proxy, InterfaceRequest<SemanticsServer>> server =
SemanticsServer.MANAGER.getInterfaceRequest(core);
mSemanticsServer = server.first;
mDartServiceProvider.connectToService(SemanticsServer.MANAGER.getName(), server.second.passHandle());
mSemanticsServer.addSemanticsListener(mAccessibilityNodeProvider);
mAccessibilityNodeProvider = new FlutterSemanticsToAndroidAccessibilityBridge(this, createSemanticsServer());
}
assert mSemanticsServer != null;
}
@Override
public AccessibilityNodeProvider getAccessibilityNodeProvider() {
ensureAccessibilityEnabled();
return mAccessibilityNodeProvider;
private SemanticsServer.Proxy createSemanticsServer() {
Core core = CoreImpl.getInstance();
Pair<SemanticsServer.Proxy, InterfaceRequest<SemanticsServer>> server =
SemanticsServer.MANAGER.getInterfaceRequest(core);
mDartServiceProvider.connectToService(SemanticsServer.MANAGER.getName(), server.second.passHandle());
return server.first;
}
void resetAccessibilityTree() {
if (mAccessibilityNodeProvider != null) {
mAccessibilityNodeProvider.reset(createSemanticsServer());
}
}
// TODO(ianh): implement touch exploration
// TODO(ianh): implement accessibility focus
void resetAccessibilityTree() {
if (mAccessibilityNodeProvider != null)
mAccessibilityNodeProvider.reset();
}
}
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册