Flutter Engine
flutter_runner::AccessibilityBridge Class Reference

#include <accessibility_bridge.h>

Inheritance diagram for flutter_runner::AccessibilityBridge:

Public Types

using SetSemanticsEnabledCallback = std::function< void(bool)>
 
using DispatchSemanticsActionCallback = std::function< void(int32_t, flutter::SemanticsAction)>
 

Public Member Functions

 AccessibilityBridge (SetSemanticsEnabledCallback set_semantics_enabled_callback, DispatchSemanticsActionCallback dispatch_semantics_action_callback, fuchsia::accessibility::semantics::SemanticsManagerHandle semantics_manager, fuchsia::ui::views::ViewRef view_ref, inspect::Node inspect_node)
 
bool GetSemanticsEnabled () const
 
void SetSemanticsEnabled (bool enabled)
 
void AddSemanticsNodeUpdate (const flutter::SemanticsNodeUpdates update, float view_pixel_ratio)
 
void RequestAnnounce (const std::string message)
 
zx_status_t OnHoverMove (double x, double y)
 
void HitTest (fuchsia::math::PointF local_point, fuchsia::accessibility::semantics::SemanticListener::HitTestCallback callback) override
 
void OnAccessibilityActionRequested (uint32_t node_id, fuchsia::accessibility::semantics::Action action, fuchsia::accessibility::semantics::SemanticListener::OnAccessibilityActionRequestedCallback callback) override
 

Static Public Attributes

static constexpr uint32_t kMaxMessageSize = ZX_CHANNEL_MAX_MSG_BYTES / 2
 
static constexpr size_t kNodeIdSize = sizeof(flutter::SemanticsNode::id)
 

Detailed Description

Definition at line 40 of file accessibility_bridge.h.

Member Typedef Documentation

◆ DispatchSemanticsActionCallback

◆ SetSemanticsEnabledCallback

Constructor & Destructor Documentation

◆ AccessibilityBridge()

flutter_runner::AccessibilityBridge::AccessibilityBridge ( SetSemanticsEnabledCallback  set_semantics_enabled_callback,
DispatchSemanticsActionCallback  dispatch_semantics_action_callback,
fuchsia::accessibility::semantics::SemanticsManagerHandle  semantics_manager,
fuchsia::ui::views::ViewRef  view_ref,
inspect::Node  inspect_node 
)

Definition at line 218 of file accessibility_bridge.cc.

References FML_LOG.

224  : set_semantics_enabled_callback_(
225  std::move(set_semantics_enabled_callback)),
226  dispatch_semantics_action_callback_(
227  std::move(dispatch_semantics_action_callback)),
228  binding_(this),
229  fuchsia_semantics_manager_(semantics_manager.Bind()),
230  inspect_node_(std::move(inspect_node)) {
231  fuchsia_semantics_manager_.set_error_handler([](zx_status_t status) {
232  FML_LOG(ERROR) << "Flutter cannot connect to SemanticsManager with status: "
233  << zx_status_get_string(status) << ".";
234  });
235  fuchsia_semantics_manager_->RegisterViewForSemantics(
236  std::move(view_ref), binding_.NewBinding(), tree_ptr_.NewRequest());
237 
238 #if !FLUTTER_RELEASE
239  // The first argument to |CreateLazyValues| is the name of the lazy node, and
240  // will only be displayed if the callback used to generate the node's content
241  // fails. Therefore, we use an error message for this node name.
242  inspect_node_tree_dump_ =
243  inspect_node_.CreateLazyValues("dump_fail", [this]() {
244  inspect::Inspector inspector;
245  if (auto it = nodes_.find(kRootNodeId); it == nodes_.end()) {
246  inspector.GetRoot().CreateString(
247  "empty_tree", "this semantic tree is empty", &inspector);
248  } else {
249  FillInspectTree(
250  kRootNodeId, /*current_level=*/1,
251  inspector.GetRoot().CreateChild(kTreeDumpInspectRootName),
252  &inspector);
253  }
254  return fpromise::make_ok_promise(std::move(inspector));
255  });
256 #endif // !FLUTTER_RELEASE
257 }
#define FML_LOG(severity)
Definition: logging.h:65
constexpr int32_t kRootNodeId

Member Function Documentation

◆ AddSemanticsNodeUpdate()

void flutter_runner::AccessibilityBridge::AddSemanticsNodeUpdate ( const flutter::SemanticsNodeUpdates  update,
float  view_pixel_ratio 
)

Definition at line 523 of file accessibility_bridge.cc.

References flutter::SemanticsNode::childrenInTraversalOrder, flutter_runner::FlutterIdToFuchsiaId(), FML_DCHECK, flutter::SemanticsNode::id, kMaxMessageSize, kNodeIdSize, flutter_runner::PrintNodeSizeError(), result, and flutter::SemanticsNode::transform.

525  {
526  if (update.empty()) {
527  return;
528  }
529  FML_DCHECK(nodes_.find(kRootNodeId) != nodes_.end() ||
530  update.find(kRootNodeId) != update.end())
531  << "AccessibilityBridge received an update with out ever getting a root "
532  "node.";
533 
534  std::vector<fuchsia::accessibility::semantics::Node> fuchsia_nodes;
535  size_t current_size = 0;
536  bool has_root_node_update = false;
537  // TODO(MI4-2498): Actions, Roles, hit test children, additional
538  // flags/states/attr
539 
540  // TODO(MI4-1478): Support for partial updates for nodes > 64kb
541  // e.g. if a node has a long label or more than 64k children.
542  for (const auto& [flutter_node_id, flutter_node] : update) {
543  size_t this_node_size = sizeof(fuchsia::accessibility::semantics::Node);
544  // We handle root update separately in GetRootNodeUpdate.
545  // TODO(chunhtai): remove this special case after we remove the inverse
546  // view pixel ratio transformation in scenic view.
547  // TODO(http://fxbug.dev/75908): Investigate flutter a11y bridge refactor
548  // after removal of the inverse view pixel ratio transformation in scenic
549  // view).
550  if (flutter_node.id == kRootNodeId) {
551  root_flutter_semantics_node_ = flutter_node;
552  has_root_node_update = true;
553  continue;
554  }
555  // Store the nodes for later hit testing and logging.
556  nodes_[flutter_node.id].data = flutter_node;
557 
558  fuchsia::accessibility::semantics::Node fuchsia_node;
559  std::vector<uint32_t> child_ids;
560  // Send the nodes in traversal order, so the manager can figure out
561  // traversal.
562  for (int32_t flutter_child_id : flutter_node.childrenInTraversalOrder) {
563  child_ids.push_back(FlutterIdToFuchsiaId(flutter_child_id));
564  }
565  // TODO(http://fxbug.dev/75910): check the usage of FlutterIdToFuchsiaId in
566  // the flutter accessibility bridge.
567  fuchsia_node.set_node_id(flutter_node.id)
568  .set_role(GetNodeRole(flutter_node))
569  .set_location(GetNodeLocation(flutter_node))
570  .set_transform(GetNodeTransform(flutter_node))
571  .set_attributes(GetNodeAttributes(flutter_node, &this_node_size))
572  .set_states(GetNodeStates(flutter_node, &this_node_size))
573  .set_actions(GetNodeActions(flutter_node, &this_node_size))
574  .set_child_ids(child_ids);
575  this_node_size +=
576  kNodeIdSize * flutter_node.childrenInTraversalOrder.size();
577 
578  // TODO(MI4-2531, FIDL-718): Remove this
579  // This is defensive. If, despite our best efforts, we ended up with a node
580  // that is larger than the max fidl size, we send no updates.
581  if (this_node_size >= kMaxMessageSize) {
582  PrintNodeSizeError(flutter_node.id);
583  return;
584  }
585  current_size += this_node_size;
586 
587  // If we would exceed the max FIDL message size by appending this node,
588  // we should delete/update/commit now.
589  if (current_size >= kMaxMessageSize) {
590  tree_ptr_->UpdateSemanticNodes(std::move(fuchsia_nodes));
591  fuchsia_nodes.clear();
592  current_size = this_node_size;
593  }
594  fuchsia_nodes.push_back(std::move(fuchsia_node));
595  }
596 
597  if (current_size > kMaxMessageSize) {
598  PrintNodeSizeError(fuchsia_nodes.back().node_id());
599  }
600 
601  // Handles root node update.
602  if (has_root_node_update || last_seen_view_pixel_ratio_ != view_pixel_ratio) {
603  last_seen_view_pixel_ratio_ = view_pixel_ratio;
604  size_t root_node_size;
605  fuchsia::accessibility::semantics::Node root_update =
606  GetRootNodeUpdate(root_node_size);
607  // TODO(MI4-2531, FIDL-718): Remove this
608  // This is defensive. If, despite our best efforts, we ended up with a node
609  // that is larger than the max fidl size, we send no updates.
610  if (root_node_size >= kMaxMessageSize) {
612  return;
613  }
614  current_size += root_node_size;
615  // If we would exceed the max FIDL message size by appending this node,
616  // we should delete/update/commit now.
617  if (current_size >= kMaxMessageSize) {
618  tree_ptr_->UpdateSemanticNodes(std::move(fuchsia_nodes));
619  fuchsia_nodes.clear();
620  }
621  fuchsia_nodes.push_back(std::move(root_update));
622  }
623 
624  PruneUnreachableNodes();
625  UpdateScreenRects();
626 
627  tree_ptr_->UpdateSemanticNodes(std::move(fuchsia_nodes));
628  // TODO(dnfield): Implement the callback here
629  // https://bugs.fuchsia.dev/p/fuchsia/issues/detail?id=35718.
630  tree_ptr_->CommitUpdates([]() {});
631 }
#define FML_DCHECK(condition)
Definition: logging.h:86
static void PrintNodeSizeError(uint32_t node_id)
static uint32_t FlutterIdToFuchsiaId(int32_t flutter_node_id)
static constexpr uint32_t kMaxMessageSize
constexpr int32_t kRootNodeId

◆ GetSemanticsEnabled()

bool flutter_runner::AccessibilityBridge::GetSemanticsEnabled ( ) const

Definition at line 259 of file accessibility_bridge.cc.

259  {
260  return semantics_enabled_;
261 }

◆ HitTest()

void flutter_runner::AccessibilityBridge::HitTest ( fuchsia::math::PointF  local_point,
fuchsia::accessibility::semantics::SemanticListener::HitTestCallback  callback 
)
override

Definition at line 790 of file accessibility_bridge.cc.

References flutter::SemanticsNode::actions, callback, flutter::SemanticsNode::childrenInHitTestOrder, flutter::data, flutter::SemanticsNode::flags, FML_DCHECK, FML_LOG, flutter::SemanticsNode::HasFlag(), flutter::SemanticsNode::hint, flutter::SemanticsNode::IsPlatformViewNode(), flutter::kIsFocusable, flutter::kIsHidden, flutter::kScopesRoute, flutter::SemanticsNode::label, and flutter::SemanticsNode::value.

793  {
794  auto hit_node_id = GetHitNode(kRootNodeId, local_point.x, local_point.y);
795  FML_DCHECK(hit_node_id.has_value());
796  fuchsia::accessibility::semantics::Hit hit;
797  // TODO(http://fxbug.dev/75910): check the usage of FlutterIdToFuchsiaId in
798  // the flutter accessibility bridge.
799  hit.set_node_id(hit_node_id.value_or(kRootNodeId));
800  callback(std::move(hit));
801 }
#define FML_DCHECK(condition)
Definition: logging.h:86
FlKeyEvent FlKeyResponderAsyncCallback callback
constexpr int32_t kRootNodeId

◆ OnAccessibilityActionRequested()

void flutter_runner::AccessibilityBridge::OnAccessibilityActionRequested ( uint32_t  node_id,
fuchsia::accessibility::semantics::Action  action,
fuchsia::accessibility::semantics::SemanticListener::OnAccessibilityActionRequestedCallback  callback 
)
override

Definition at line 763 of file accessibility_bridge.cc.

References action, callback, and FML_LOG.

767  {
768  // TODO(http://fxbug.dev/75910): check the usage of FlutterIdToFuchsiaId in
769  // the flutter accessibility bridge.
770  if (nodes_.find(node_id) == nodes_.end()) {
771  FML_LOG(ERROR) << "Attempted to send accessibility action "
772  << static_cast<int32_t>(action)
773  << " to unknown node id: " << node_id;
774  callback(false);
775  return;
776  }
777 
778  std::optional<flutter::SemanticsAction> flutter_action =
779  GetFlutterSemanticsAction(action, node_id);
780  if (!flutter_action.has_value()) {
781  callback(false);
782  return;
783  }
784  dispatch_semantics_action_callback_(static_cast<int32_t>(node_id),
785  flutter_action.value());
786  callback(true);
787 }
#define FML_LOG(severity)
Definition: logging.h:65
FlKeyEvent FlKeyResponderAsyncCallback callback
SemanticsAction action

◆ OnHoverMove()

zx_status_t flutter_runner::AccessibilityBridge::OnHoverMove ( double  x,
double  y 
)

◆ RequestAnnounce()

void flutter_runner::AccessibilityBridge::RequestAnnounce ( const std::string  message)

Definition at line 668 of file accessibility_bridge.cc.

References flutter::SemanticsNode::childrenInHitTestOrder, FML_DLOG, FML_LOG, flutter::kDecrease, flutter::kIncrease, flutter::kLongPress, flutter::kShowOnScreen, flutter::kTap, flutter::SemanticsNode::rect, and flutter::SemanticsNode::transform.

668  {
669  fuchsia::accessibility::semantics::SemanticEvent semantic_event;
670  fuchsia::accessibility::semantics::AnnounceEvent announce_event;
671  announce_event.set_message(message);
672  semantic_event.set_announce(std::move(announce_event));
673 
674  tree_ptr_->SendSemanticEvent(std::move(semantic_event), []() {});
675 }

◆ SetSemanticsEnabled()

Member Data Documentation

◆ kMaxMessageSize

constexpr uint32_t flutter_runner::AccessibilityBridge::kMaxMessageSize = ZX_CHANNEL_MAX_MSG_BYTES / 2
static

◆ kNodeIdSize

constexpr size_t flutter_runner::AccessibilityBridge::kNodeIdSize = sizeof(flutter::SemanticsNode::id)
static

The documentation for this class was generated from the following files: