From abd918eb618bfcc9a1a07513f88dfc066ea4aa3c Mon Sep 17 00:00:00 2001 From: Jonah Williams Date: Thu, 13 Sep 2018 10:28:27 -0700 Subject: [PATCH] Add scrollIndex and scrollChildren to semantics, add Android implementation (#6239) --- lib/ui/semantics.dart | 10 ++++++++- lib/ui/semantics/semantics_node.h | 2 ++ lib/ui/semantics/semantics_update_builder.cc | 4 ++++ lib/ui/semantics/semantics_update_builder.h | 2 ++ .../io/flutter/view/AccessibilityBridge.java | 22 +++++++++++++++++-- .../platform/android/platform_view_android.cc | 4 +++- 6 files changed, 40 insertions(+), 4 deletions(-) diff --git a/lib/ui/semantics.dart b/lib/ui/semantics.dart index 444ea8856261b..e4bc18b81ffd8 100644 --- a/lib/ui/semantics.dart +++ b/lib/ui/semantics.dart @@ -596,7 +596,9 @@ class SemanticsUpdateBuilder extends NativeFieldWrapperClass2 { /// describe the maximum and minimum in-rage values that `scrollPosition` can /// be. Both or either may be infinity to indicate unbound scrolling. The /// value for `scrollPosition` can (temporarily) be outside this range, for - /// example during an overscroll. + /// example during an overscroll. `scrollChildren` is the count of the + /// total number of child nodes that contribute semantics and `scrollIndex` + /// is the index of the first visible child node that contributes semantics. /// /// The `rect` is the region occupied by this node in its own coordinate /// system. @@ -609,6 +611,8 @@ class SemanticsUpdateBuilder extends NativeFieldWrapperClass2 { int actions, int textSelectionBase, int textSelectionExtent, + int scrollChildren, + int scrollIndex, double scrollPosition, double scrollExtentMax, double scrollExtentMin, @@ -634,6 +638,8 @@ class SemanticsUpdateBuilder extends NativeFieldWrapperClass2 { actions, textSelectionBase, textSelectionExtent, + scrollChildren, + scrollIndex, scrollPosition, scrollExtentMax, scrollExtentMin, @@ -659,6 +665,8 @@ class SemanticsUpdateBuilder extends NativeFieldWrapperClass2 { int actions, int textSelectionBase, int textSelectionExtent, + int scrollChildren, + int scrollIndex, double scrollPosition, double scrollExtentMax, double scrollExtentMin, diff --git a/lib/ui/semantics/semantics_node.h b/lib/ui/semantics/semantics_node.h index 2ade1f49a905b..e5d405d38e716 100644 --- a/lib/ui/semantics/semantics_node.h +++ b/lib/ui/semantics/semantics_node.h @@ -79,6 +79,8 @@ struct SemanticsNode { int32_t actions = 0; int32_t textSelectionBase = -1; int32_t textSelectionExtent = -1; + int32_t scrollChildren = 0; + int32_t scrollIndex = 0; double scrollPosition = std::nan(""); double scrollExtentMax = std::nan(""); double scrollExtentMin = std::nan(""); diff --git a/lib/ui/semantics/semantics_update_builder.cc b/lib/ui/semantics/semantics_update_builder.cc index 8c53103808c58..5536029565518 100644 --- a/lib/ui/semantics/semantics_update_builder.cc +++ b/lib/ui/semantics/semantics_update_builder.cc @@ -41,6 +41,8 @@ void SemanticsUpdateBuilder::updateNode( int actions, int textSelectionBase, int textSelectionExtent, + int scrollChildren, + int scrollIndex, double scrollPosition, double scrollExtentMax, double scrollExtentMin, @@ -64,6 +66,8 @@ void SemanticsUpdateBuilder::updateNode( node.actions = actions; node.textSelectionBase = textSelectionBase; node.textSelectionExtent = textSelectionExtent; + node.scrollChildren = scrollChildren; + node.scrollIndex = scrollIndex; node.scrollPosition = scrollPosition; node.scrollExtentMax = scrollExtentMax; node.scrollExtentMin = scrollExtentMin; diff --git a/lib/ui/semantics/semantics_update_builder.h b/lib/ui/semantics/semantics_update_builder.h index 5fa9f2f4bf2da..a9422afba6cae 100644 --- a/lib/ui/semantics/semantics_update_builder.h +++ b/lib/ui/semantics/semantics_update_builder.h @@ -29,6 +29,8 @@ class SemanticsUpdateBuilder int actions, int textSelectionBase, int textSelectionExtent, + int scrollChildren, + int scrollIndex, double scrollPosition, double scrollExtentMax, double scrollExtentMin, diff --git a/shell/platform/android/io/flutter/view/AccessibilityBridge.java b/shell/platform/android/io/flutter/view/AccessibilityBridge.java index ba15c33428c6b..807e46b2a9bd1 100644 --- a/shell/platform/android/io/flutter/view/AccessibilityBridge.java +++ b/shell/platform/android/io/flutter/view/AccessibilityBridge.java @@ -144,8 +144,8 @@ public AccessibilityNodeInfo createAccessibilityNodeInfo(int virtualViewId) { } AccessibilityNodeInfo result = AccessibilityNodeInfo.obtain(mOwner, virtualViewId); - // Work around for https://github.com/flutter/flutter/issues/2101 - result.setViewIdResourceName(""); + // Work around for https://github.com/flutter/flutter/issues/2101 + result.setViewIdResourceName(""); result.setPackageName(mOwner.getContext().getPackageName()); result.setClassName("android.view.View"); result.setSource(mOwner, virtualViewId); @@ -717,6 +717,20 @@ void updateSemantics(ByteBuffer buffer, String[] strings) { event.setScrollX((int) position); event.setMaxScrollX((int) max); } + if (object.scrollChildren > 0) { + event.setItemCount(object.scrollChildren); + event.setFromIndex(object.scrollIndex); + int visibleChildren = object.childrenInHitTestOrder.size() - 1; + // We assume that only children at the end of the list can be hidden. + assert(!object.childrenInHitTestOrder.get(object.scrollIndex).hasFlag(Flag.IS_HIDDEN)); + for (; visibleChildren >= 0; visibleChildren--) { + SemanticsObject child = object.childrenInHitTestOrder.get(visibleChildren); + if (!child.hasFlag(Flag.IS_HIDDEN)) { + break; + } + } + event.setToIndex(object.scrollIndex + visibleChildren); + } sendAccessibilityEvent(event); } if (object.hasFlag(Flag.IS_LIVE_REGION) && !object.hadFlag(Flag.IS_LIVE_REGION)) { @@ -947,6 +961,8 @@ private class SemanticsObject { int actions; int textSelectionBase; int textSelectionExtent; + int scrollChildren; + int scrollIndex; float scrollPosition; float scrollExtentMax; float scrollExtentMin; @@ -1048,6 +1064,8 @@ void updateWith(ByteBuffer buffer, String[] strings) { actions = buffer.getInt(); textSelectionBase = buffer.getInt(); textSelectionExtent = buffer.getInt(); + scrollChildren = buffer.getInt(); + scrollIndex = buffer.getInt(); scrollPosition = buffer.getFloat(); scrollExtentMax = buffer.getFloat(); scrollExtentMin = buffer.getFloat(); diff --git a/shell/platform/android/platform_view_android.cc b/shell/platform/android/platform_view_android.cc index eea7593e06a18..ee82b44e51604 100644 --- a/shell/platform/android/platform_view_android.cc +++ b/shell/platform/android/platform_view_android.cc @@ -207,7 +207,7 @@ void PlatformViewAndroid::DispatchSemanticsAction(JNIEnv* env, void PlatformViewAndroid::UpdateSemantics( blink::SemanticsNodeUpdates update, blink::CustomAccessibilityActionUpdates actions) { - constexpr size_t kBytesPerNode = 36 * sizeof(int32_t); + constexpr size_t kBytesPerNode = 38 * sizeof(int32_t); constexpr size_t kBytesPerChild = sizeof(int32_t); constexpr size_t kBytesPerAction = 4 * sizeof(int32_t); @@ -243,6 +243,8 @@ void PlatformViewAndroid::UpdateSemantics( buffer_int32[position++] = node.actions; buffer_int32[position++] = node.textSelectionBase; buffer_int32[position++] = node.textSelectionExtent; + buffer_int32[position++] = node.scrollChildren; + buffer_int32[position++] = node.scrollIndex; buffer_float32[position++] = (float)node.scrollPosition; buffer_float32[position++] = (float)node.scrollExtentMax; buffer_float32[position++] = (float)node.scrollExtentMin;