• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 "flutter/fml/thread_local.h"
8 
9 namespace {
10 
11 using ViewHolderBindings =
12     std::unordered_map<zx_koid_t, std::unique_ptr<flutter::ViewHolder>>;
13 
14 FML_THREAD_LOCAL fml::ThreadLocalUniquePtr<ViewHolderBindings>
15     tls_view_holder_bindings;
16 
ToViewProperties(float width,float height,float insetTop,float insetRight,float insetBottom,float insetLeft,bool focusable)17 fuchsia::ui::gfx::ViewProperties ToViewProperties(float width,
18                                                   float height,
19                                                   float insetTop,
20                                                   float insetRight,
21                                                   float insetBottom,
22                                                   float insetLeft,
23                                                   bool focusable) {
24   return fuchsia::ui::gfx::ViewProperties({
25       .bounding_box = fuchsia::ui::gfx::BoundingBox({
26           .min = fuchsia::ui::gfx::vec3({
27               .x = 0.f,
28               .y = 0.f,
29               .z = -1000.f,
30           }),
31           .max = fuchsia::ui::gfx::vec3({.x = width, .y = height, .z = 0.f}),
32       }),
33       .inset_from_min = fuchsia::ui::gfx::vec3({
34           .x = insetLeft,
35           .y = insetTop,
36           .z = 0.f,
37       }),
38       .inset_from_max = fuchsia::ui::gfx::vec3({
39           .x = insetRight,
40           .y = insetBottom,
41           .z = 0.f,
42       }),
43       .focus_change = focusable,
44   });
45 }
46 
47 }  // namespace
48 
49 namespace flutter {
50 
Create(zx_koid_t id,fml::RefPtr<fml::TaskRunner> ui_task_runner,fuchsia::ui::views::ViewHolderToken view_holder_token,BindCallback on_bind_callback)51 void ViewHolder::Create(zx_koid_t id,
52                         fml::RefPtr<fml::TaskRunner> ui_task_runner,
53                         fuchsia::ui::views::ViewHolderToken view_holder_token,
54                         BindCallback on_bind_callback) {
55   // This GPU thread contains at least 1 ViewHolder.  Initialize the per-thread
56   // bindings.
57   if (tls_view_holder_bindings.get() == nullptr) {
58     tls_view_holder_bindings.reset(new ViewHolderBindings());
59   }
60 
61   auto* bindings = tls_view_holder_bindings.get();
62   FML_DCHECK(bindings);
63   FML_DCHECK(bindings->find(id) == bindings->end());
64 
65   auto view_holder = std::make_unique<ViewHolder>(std::move(ui_task_runner),
66                                                   std::move(view_holder_token),
67                                                   std::move(on_bind_callback));
68   bindings->emplace(id, std::move(view_holder));
69 }
70 
Destroy(zx_koid_t id)71 void ViewHolder::Destroy(zx_koid_t id) {
72   auto* bindings = tls_view_holder_bindings.get();
73   FML_DCHECK(bindings);
74 
75   bindings->erase(id);
76 }
77 
FromId(zx_koid_t id)78 ViewHolder* ViewHolder::FromId(zx_koid_t id) {
79   auto* bindings = tls_view_holder_bindings.get();
80   if (!bindings) {
81     return nullptr;
82   }
83 
84   auto binding = bindings->find(id);
85   if (binding == bindings->end()) {
86     return nullptr;
87   }
88 
89   return binding->second.get();
90 }
91 
ViewHolder(fml::RefPtr<fml::TaskRunner> ui_task_runner,fuchsia::ui::views::ViewHolderToken view_holder_token,BindCallback on_bind_callback)92 ViewHolder::ViewHolder(fml::RefPtr<fml::TaskRunner> ui_task_runner,
93                        fuchsia::ui::views::ViewHolderToken view_holder_token,
94                        BindCallback on_bind_callback)
95     : ui_task_runner_(std::move(ui_task_runner)),
96       pending_view_holder_token_(std::move(view_holder_token)),
97       pending_bind_callback_(std::move(on_bind_callback)) {
98   FML_DCHECK(ui_task_runner_);
99   FML_DCHECK(pending_view_holder_token_.value);
100 }
101 
UpdateScene(SceneUpdateContext & context,const SkPoint & offset,const SkSize & size,bool hit_testable)102 void ViewHolder::UpdateScene(SceneUpdateContext& context,
103                              const SkPoint& offset,
104                              const SkSize& size,
105                              bool hit_testable) {
106   if (pending_view_holder_token_.value) {
107     opacity_node_ =
108         std::make_unique<scenic::OpacityNodeHACK>(context.session());
109     entity_node_ = std::make_unique<scenic::EntityNode>(context.session());
110     view_holder_ = std::make_unique<scenic::ViewHolder>(
111         context.session(), std::move(pending_view_holder_token_),
112         "Flutter SceneHost");
113 
114     opacity_node_->AddChild(*entity_node_);
115     entity_node_->Attach(*view_holder_);
116     ui_task_runner_->PostTask(
117         [bind_callback = std::move(pending_bind_callback_),
118          view_holder_id = view_holder_->id()]() {
119           bind_callback(view_holder_id);
120         });
121   }
122   FML_DCHECK(opacity_node_);
123   FML_DCHECK(view_holder_);
124 
125   context.top_entity()->entity_node().AddChild(*opacity_node_);
126   entity_node_->SetTranslation(offset.x(), offset.y(), -0.1f);
127   entity_node_->SetHitTestBehavior(
128       hit_testable ? fuchsia::ui::gfx::HitTestBehavior::kDefault
129                    : fuchsia::ui::gfx::HitTestBehavior::kSuppress);
130   if (has_pending_opacity_) {
131     opacity_node_->SetOpacity(pending_opacity_);
132 
133     has_pending_opacity_ = false;
134   }
135   if (has_pending_properties_) {
136     view_holder_->SetViewProperties(std::move(pending_properties_));
137 
138     has_pending_properties_ = false;
139   }
140 }
141 
SetProperties(double width,double height,double insetTop,double insetRight,double insetBottom,double insetLeft,bool focusable)142 void ViewHolder::SetProperties(double width,
143                                double height,
144                                double insetTop,
145                                double insetRight,
146                                double insetBottom,
147                                double insetLeft,
148                                bool focusable) {
149   pending_properties_ = ToViewProperties(width, height, insetTop, insetRight,
150                                          insetBottom, insetLeft, focusable);
151   has_pending_properties_ = true;
152 }
153 
SetOpacity(double opacity)154 void ViewHolder::SetOpacity(double opacity) {
155   pending_opacity_ = std::clamp(opacity, 0.0, 1.0);
156   has_pending_opacity_ = true;
157 }
158 
159 }  // namespace flutter
160