Flutter Engine
flutter_runner::AccessibilityBridge Class Reference

#include <accessibility_bridge.h>

Inheritance diagram for flutter_runner::AccessibilityBridge:

Classes

class  Delegate
 

Public Member Functions

 AccessibilityBridge (Delegate &delegate, const std::shared_ptr< sys::ServiceDirectory > services, fuchsia::ui::views::ViewRef view_ref)
 
bool GetSemanticsEnabled () const
 
void SetSemanticsEnabled (bool enabled)
 
void AddSemanticsNodeUpdate (const flutter::SemanticsNodeUpdates update, float view_pixel_ratio)
 
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.

Constructor & Destructor Documentation

◆ AccessibilityBridge()

flutter_runner::AccessibilityBridge::AccessibilityBridge ( Delegate delegate,
const std::shared_ptr< sys::ServiceDirectory >  services,
fuchsia::ui::views::ViewRef  view_ref 
)

Definition at line 16 of file accessibility_bridge.cc.

References FML_LOG.

20  : delegate_(delegate), binding_(this) {
21  services->Connect(fuchsia::accessibility::semantics::SemanticsManager::Name_,
22  fuchsia_semantics_manager_.NewRequest().TakeChannel());
23  fuchsia_semantics_manager_.set_error_handler([](zx_status_t status) {
24  FML_LOG(ERROR) << "Flutter cannot connect to SemanticsManager with status: "
25  << zx_status_get_string(status) << ".";
26  });
27  fidl::InterfaceHandle<fuchsia::accessibility::semantics::SemanticListener>
28  listener_handle;
29  binding_.Bind(listener_handle.NewRequest());
30  fuchsia_semantics_manager_->RegisterViewForSemantics(
31  std::move(view_ref), std::move(listener_handle), tree_ptr_.NewRequest());
32 }
#define FML_LOG(severity)
Definition: logging.h:65
MockDelegate delegate_

Member Function Documentation

◆ AddSemanticsNodeUpdate()

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

Definition at line 272 of file accessibility_bridge.cc.

References flutter::SemanticsNode::childrenInHitTestOrder, flutter::SemanticsNode::childrenInTraversalOrder, flutter::SemanticsNode::flags, flutter_runner::FlutterIdToFuchsiaId(), FML_DCHECK, FML_DLOG, FML_LOG, flutter::SemanticsNode::id, flutter::kDecrease, flutter::kIncrease, flutter::kLongPress, kMaxMessageSize, kNodeIdSize, flutter::kShowOnScreen, flutter::kTap, flutter_runner::PrintNodeSizeError(), flutter::SemanticsNode::rect, flutter::SemanticsNode::transform, and value.

274  {
275  if (update.empty()) {
276  return;
277  }
278  FML_DCHECK(nodes_.find(kRootNodeId) != nodes_.end() ||
279  update.find(kRootNodeId) != update.end())
280  << "AccessibilityBridge received an update with out ever getting a root "
281  "node.";
282 
283  std::vector<fuchsia::accessibility::semantics::Node> nodes;
284  size_t current_size = 0;
285  bool has_root_node_update = false;
286  // TODO(MI4-2498): Actions, Roles, hit test children, additional
287  // flags/states/attr
288 
289  // TODO(MI4-1478): Support for partial updates for nodes > 64kb
290  // e.g. if a node has a long label or more than 64k children.
291  for (const auto& value : update) {
292  size_t this_node_size = sizeof(fuchsia::accessibility::semantics::Node);
293  const auto& flutter_node = value.second;
294  // We handle root update separately in GetRootNodeUpdate.
295  // TODO(chunhtai): remove this special case after we remove the inverse
296  // view pixel ratio transformation in scenic view.
297  if (flutter_node.id == kRootNodeId) {
298  root_flutter_semantics_node_ = flutter_node;
299  has_root_node_update = true;
300  continue;
301  }
302  // Store the nodes for later hit testing.
303  nodes_[flutter_node.id] = {
304  .id = flutter_node.id,
305  .flags = flutter_node.flags,
306  .rect = flutter_node.rect,
307  .transform = flutter_node.transform,
308  .children_in_hit_test_order = flutter_node.childrenInHitTestOrder,
309  };
310  fuchsia::accessibility::semantics::Node fuchsia_node;
311  std::vector<uint32_t> child_ids;
312  // Send the nodes in traversal order, so the manager can figure out
313  // traversal.
314  for (int32_t flutter_child_id : flutter_node.childrenInTraversalOrder) {
315  child_ids.push_back(FlutterIdToFuchsiaId(flutter_child_id));
316  }
317  fuchsia_node.set_node_id(flutter_node.id)
318  .set_role(GetNodeRole(flutter_node))
319  .set_location(GetNodeLocation(flutter_node))
320  .set_transform(GetNodeTransform(flutter_node))
321  .set_attributes(GetNodeAttributes(flutter_node, &this_node_size))
322  .set_states(GetNodeStates(flutter_node, &this_node_size))
323  .set_actions(GetNodeActions(flutter_node, &this_node_size))
324  .set_role(GetNodeRole(flutter_node))
325  .set_child_ids(child_ids);
326  this_node_size +=
327  kNodeIdSize * flutter_node.childrenInTraversalOrder.size();
328 
329  // TODO(MI4-2531, FIDL-718): Remove this
330  // This is defensive. If, despite our best efforts, we ended up with a node
331  // that is larger than the max fidl size, we send no updates.
332  if (this_node_size >= kMaxMessageSize) {
333  PrintNodeSizeError(flutter_node.id);
334  return;
335  }
336  current_size += this_node_size;
337 
338  // If we would exceed the max FIDL message size by appending this node,
339  // we should delete/update/commit now.
340  if (current_size >= kMaxMessageSize) {
341  tree_ptr_->UpdateSemanticNodes(std::move(nodes));
342  nodes.clear();
343  current_size = this_node_size;
344  }
345  nodes.push_back(std::move(fuchsia_node));
346  }
347 
348  if (current_size > kMaxMessageSize) {
349  PrintNodeSizeError(nodes.back().node_id());
350  }
351 
352  // Handles root node update.
353  if (has_root_node_update || last_seen_view_pixel_ratio_ != view_pixel_ratio) {
354  last_seen_view_pixel_ratio_ = view_pixel_ratio;
355  size_t root_node_size;
356  fuchsia::accessibility::semantics::Node root_update =
357  GetRootNodeUpdate(root_node_size);
358  // TODO(MI4-2531, FIDL-718): Remove this
359  // This is defensive. If, despite our best efforts, we ended up with a node
360  // that is larger than the max fidl size, we send no updates.
361  if (root_node_size >= kMaxMessageSize) {
363  return;
364  }
365  current_size += root_node_size;
366  // If we would exceed the max FIDL message size by appending this node,
367  // we should delete/update/commit now.
368  if (current_size >= kMaxMessageSize) {
369  tree_ptr_->UpdateSemanticNodes(std::move(nodes));
370  nodes.clear();
371  }
372  nodes.push_back(std::move(root_update));
373  }
374 
375  PruneUnreachableNodes();
376  UpdateScreenRects();
377 
378  tree_ptr_->UpdateSemanticNodes(std::move(nodes));
379  // TODO(dnfield): Implement the callback here
380  // https://bugs.fuchsia.dev/p/fuchsia/issues/detail?id=35718.
381  tree_ptr_->CommitUpdates([]() {});
382 }
#define FML_DCHECK(condition)
Definition: logging.h:86
uint8_t value
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 34 of file accessibility_bridge.cc.

34  {
35  return semantics_enabled_;
36 }

◆ HitTest()

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

Definition at line 522 of file accessibility_bridge.cc.

References flutter::SemanticsNode::flags, FML_DCHECK, FML_LOG, flutter::kIsHidden, and flutter_runner::AccessibilityBridge::Delegate::SetSemanticsEnabled().

525  {
526  auto hit_node_id = GetHitNode(kRootNodeId, local_point.x, local_point.y);
527  FML_DCHECK(hit_node_id.has_value());
528  fuchsia::accessibility::semantics::Hit hit;
529  hit.set_node_id(hit_node_id.value_or(kRootNodeId));
530  callback(std::move(hit));
531 }
#define FML_DCHECK(condition)
Definition: logging.h:86
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 497 of file accessibility_bridge.cc.

References action, flutter_runner::AccessibilityBridge::Delegate::DispatchSemanticsAction(), and FML_LOG.

501  {
502  if (nodes_.find(node_id) == nodes_.end()) {
503  FML_LOG(ERROR) << "Attempted to send accessibility action "
504  << static_cast<int32_t>(action)
505  << " to unkonwn node id: " << node_id;
506  callback(false);
507  return;
508  }
509 
510  std::optional<flutter::SemanticsAction> flutter_action =
511  GetFlutterSemanticsAction(action, node_id);
512  if (!flutter_action.has_value()) {
513  callback(false);
514  return;
515  }
516  delegate_.DispatchSemanticsAction(static_cast<int32_t>(node_id),
517  flutter_action.value());
518  callback(true);
519 }
#define FML_LOG(severity)
Definition: logging.h:65
MockDelegate delegate_
SemanticsAction action

◆ OnHoverMove()

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

◆ 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: