Flutter Engine
view_holder.cc
Go to the documentation of this file.
1 // Copyright 2013 The Flutter Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #include "flutter/flow/view_holder.h"
6 
7 #include <unordered_map>
8 
9 #include "flutter/fml/thread_local.h"
10 
11 namespace {
12 
13 using ViewHolderBindings =
14  std::unordered_map<zx_koid_t, std::unique_ptr<flutter::ViewHolder>>;
15 
17  tls_view_holder_bindings;
18 
19 fuchsia::ui::gfx::ViewProperties ToViewProperties(float width,
20  float height,
21  float insetTop,
22  float insetRight,
23  float insetBottom,
24  float insetLeft,
25  bool focusable) {
26  return fuchsia::ui::gfx::ViewProperties({
27  .bounding_box = fuchsia::ui::gfx::BoundingBox({
28  .min = fuchsia::ui::gfx::vec3({
29  .x = 0.f,
30  .y = 0.f,
31  .z = -1000.f,
32  }),
33  .max = fuchsia::ui::gfx::vec3({.x = width, .y = height, .z = 0.f}),
34  }),
35  .inset_from_min = fuchsia::ui::gfx::vec3({
36  .x = insetLeft,
37  .y = insetTop,
38  .z = 0.f,
39  }),
40  .inset_from_max = fuchsia::ui::gfx::vec3({
41  .x = insetRight,
42  .y = insetBottom,
43  .z = 0.f,
44  }),
45  .focus_change = focusable,
46  });
47 }
48 
49 } // namespace
50 
51 namespace flutter {
52 
53 void ViewHolder::Create(zx_koid_t id,
54  fml::RefPtr<fml::TaskRunner> ui_task_runner,
55  fuchsia::ui::views::ViewHolderToken view_holder_token,
56  const BindCallback& on_bind_callback) {
57  // This raster thread contains at least 1 ViewHolder. Initialize the
58  // per-thread bindings.
59  if (tls_view_holder_bindings.get() == nullptr) {
60  tls_view_holder_bindings.reset(new ViewHolderBindings());
61  }
62 
63  auto* bindings = tls_view_holder_bindings.get();
64  FML_DCHECK(bindings);
65  FML_DCHECK(bindings->find(id) == bindings->end());
66 
67  auto view_holder = std::make_unique<ViewHolder>(std::move(ui_task_runner),
68  std::move(view_holder_token),
69  on_bind_callback);
70  bindings->emplace(id, std::move(view_holder));
71 }
72 
73 void ViewHolder::Destroy(zx_koid_t id) {
74  auto* bindings = tls_view_holder_bindings.get();
75  FML_DCHECK(bindings);
76 
77  bindings->erase(id);
78 }
79 
81  auto* bindings = tls_view_holder_bindings.get();
82  if (!bindings) {
83  return nullptr;
84  }
85 
86  auto binding = bindings->find(id);
87  if (binding == bindings->end()) {
88  return nullptr;
89  }
90 
91  return binding->second.get();
92 }
93 
95  fuchsia::ui::views::ViewHolderToken view_holder_token,
96  const BindCallback& on_bind_callback)
97  : ui_task_runner_(std::move(ui_task_runner)),
98  pending_view_holder_token_(std::move(view_holder_token)),
99  pending_bind_callback_(on_bind_callback) {
100  FML_DCHECK(pending_view_holder_token_.value);
101 }
102 
103 void ViewHolder::UpdateScene(scenic::Session* session,
104  scenic::ContainerNode& container_node,
105  const SkPoint& offset,
106  const SkSize& size,
107  SkAlpha opacity,
108  bool hit_testable) {
109  if (pending_view_holder_token_.value) {
110  entity_node_ = std::make_unique<scenic::EntityNode>(session);
111  opacity_node_ = std::make_unique<scenic::OpacityNodeHACK>(session);
112  view_holder_ = std::make_unique<scenic::ViewHolder>(
113  session, std::move(pending_view_holder_token_), "Flutter SceneHost");
114  opacity_node_->AddChild(*entity_node_);
115  opacity_node_->SetLabel("flutter::ViewHolder");
116  entity_node_->Attach(*view_holder_);
117  if (ui_task_runner_ && pending_view_holder_token_.value) {
118  ui_task_runner_->PostTask(
119  [bind_callback = std::move(pending_bind_callback_),
120  view_holder_id = view_holder_->id()]() {
121  bind_callback(view_holder_id);
122  });
123  }
124  }
125  FML_DCHECK(entity_node_);
126  FML_DCHECK(opacity_node_);
127  FML_DCHECK(view_holder_);
128 
129  container_node.AddChild(*opacity_node_);
130  opacity_node_->SetOpacity(opacity / 255.0f);
131  entity_node_->SetTranslation(offset.x(), offset.y(), -0.1f);
132  entity_node_->SetHitTestBehavior(
133  hit_testable ? fuchsia::ui::gfx::HitTestBehavior::kDefault
134  : fuchsia::ui::gfx::HitTestBehavior::kSuppress);
135  if (has_pending_properties_) {
136  // TODO(dworsham): This should be derived from size and elevation. We
137  // should be able to Z-limit the view's box but otherwise it uses all of the
138  // available airspace.
139  view_holder_->SetViewProperties(std::move(pending_properties_));
140 
141  has_pending_properties_ = false;
142  }
143 }
144 
145 void ViewHolder::SetProperties(double width,
146  double height,
147  double insetTop,
148  double insetRight,
149  double insetBottom,
150  double insetLeft,
151  bool focusable) {
152  pending_properties_ = ToViewProperties(width, height, insetTop, insetRight,
153  insetBottom, insetLeft, focusable);
154  has_pending_properties_ = true;
155 }
156 
157 } // namespace flutter
#define FML_DCHECK(condition)
Definition: logging.h:86
void UpdateScene(scenic::Session *session, scenic::ContainerNode &container_node, const SkPoint &offset, const SkSize &size, SkAlpha opacity, bool hit_testable)
Definition: view_holder.cc:103
void SetProperties(double width, double height, double insetTop, double insetRight, double insetBottom, double insetLeft, bool focusable)
Definition: view_holder.cc:145
Definition: ref_ptr.h:252
std::function< void(scenic::ResourceId)> BindCallback
Definition: view_holder.h:32
virtual void PostTask(const fml::closure &task)
Definition: task_runner.cc:24
constexpr std::size_t size(T(&array)[N])
Definition: size.h:13
#define FML_THREAD_LOCAL
Definition: thread_local.h:61
int32_t height
int32_t width
static void Destroy(zx_koid_t id)
Definition: view_holder.cc:73
static void Create(zx_koid_t id, fml::RefPtr< fml::TaskRunner > ui_task_runner, fuchsia::ui::views::ViewHolderToken view_holder_token, const BindCallback &on_bind_callback)
Definition: view_holder.cc:53
static ViewHolder * FromId(zx_koid_t id)
Definition: view_holder.cc:80
ViewHolder(fml::RefPtr< fml::TaskRunner > ui_task_runner, fuchsia::ui::views::ViewHolderToken view_holder_token, const BindCallback &on_bind_callback)
Definition: view_holder.cc:94