blob: 232acf68ed2ac8bcf3fdb3a3d8a14d2c763ff611 [file] [log] [blame]
// Copyright 2020 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "view_wrapper.h"
#include <fuchsia/accessibility/semantics/cpp/fidl.h>
#include <lib/async/default.h>
#include <lib/syslog/cpp/macros.h>
#include <stack>
#include "src/ui/a11y/lib/semantics/util/semantic_transform.h"
namespace a11y {
ViewWrapper::ViewWrapper(fuchsia::ui::views::ViewRef view_ref,
std::unique_ptr<ViewSemantics> view_semantics,
std::unique_ptr<AnnotationViewInterface> annotation_view)
: view_ref_(std::move(view_ref)),
view_semantics_(std::move(view_semantics)),
annotation_view_(std::move(annotation_view)) {}
void ViewWrapper::EnableSemanticUpdates(bool enabled) {
view_semantics_->EnableSemanticUpdates(enabled);
}
fxl::WeakPtr<::a11y::SemanticTree> ViewWrapper::GetTree() { return view_semantics_->GetTree(); }
fuchsia::ui::views::ViewRef ViewWrapper::ViewRefClone() const { return Clone(view_ref_); }
void ViewWrapper::HighlightNode(uint32_t node_id) {
auto tree_weak_ptr = GetTree();
if (!tree_weak_ptr) {
FX_LOGS(ERROR) << "ViewWrapper::DrawHighlight: Invalid tree pointer";
return;
}
auto annotated_node = tree_weak_ptr->GetNode(node_id);
if (!annotated_node) {
FX_LOGS(ERROR) << "ViewWrapper::DrawHighlight: No node found with id: " << node_id;
return;
}
// Compute the translation and scaling vectors for the node's bounding box.
// Each node can supply a 4x4 transform matrix of the form:
// [ Sx 0 0 Tx ]
// [ 0 Sy 0 Ty ]
// [ 0 0 Sz Tz ]
// [ 0 0 0 1 ]
//
// Here, Sx, Sy, and Sz are the scale coefficients on the x, y, and z axes,
// respectively. Tx, Ty, and Tz are the x, y, and z components of translation,
// respectively.
//
// In order to compute the transform matrix from the focused node's coordinate
// space to the root node's coordinate space, we can simply compute the
// cross product of the focused node's ancestors' transform matrices,
// beginning at the focused node and up to the minimum-depth non-root ancestor
// (the root does not have a parent, so it does not need a transform).
//
// [Focused node to root transform] = [depth 1 ancestor transform] x
// [depth 2 ancestor transform] x ... x [parent transform] x [focused node transform]
//
// The resulting transform will be of the same form as described above. Using
// this matrix, we can simply extract the scaling and translation vectors
// required by scenic: (Sx, Sy, Sz) and (Tx, Ty, Tz), respectively.
uint32_t current_node_id = annotated_node->node_id();
SemanticTransform transform;
while (current_node_id != 0) {
auto current_node = tree_weak_ptr->GetNode(current_node_id);
FX_DCHECK(current_node);
if (current_node->has_transform()) {
transform.ChainLocalTransform(current_node->transform());
}
auto parent_node = tree_weak_ptr->GetParentNode(current_node_id);
FX_DCHECK(parent_node);
current_node_id = parent_node->node_id();
}
auto bounding_box = annotated_node->location();
annotation_view_->DrawHighlight(bounding_box, transform.scale_vector(),
transform.translation_vector());
}
void ViewWrapper::ClearHighlights() { annotation_view_->DetachViewContents(); }
} // namespace a11y