Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(139)

Side by Side Diff: examples/ui/tile/tile_view.cc

Issue 1559723002: Update the UI examples. (Closed) Base URL: git@github.com:domokit/mojo.git@moz-14
Patch Set: address feedback Created 4 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « examples/ui/tile/tile_view.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2015 The Chromium Authors. All rights reserved. 1 // Copyright 2015 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "base/bind.h"
5 #include "examples/ui/tile/tile_view.h" 6 #include "examples/ui/tile/tile_view.h"
6 #include "mojo/services/surfaces/cpp/surfaces_utils.h" 7 #include "mojo/services/geometry/cpp/geometry_util.h"
7 #include "mojo/services/surfaces/interfaces/quads.mojom.h"
8 8
9 namespace examples { 9 namespace examples {
10 10
11 namespace {
12 constexpr uint32_t kViewResourceIdBase = 100;
13 constexpr uint32_t kViewResourceIdSpacing = 100;
14
15 constexpr uint32_t kRootNodeId = mojo::gfx::composition::kSceneRootNodeId;
16 constexpr uint32_t kViewNodeIdBase = 100;
17 constexpr uint32_t kViewNodeIdSpacing = 100;
18 constexpr uint32_t kViewSceneNodeIdOffset = 1;
19 constexpr uint32_t kViewFallbackNodeIdOffset = 2;
20 } // namespace
21
11 TileView::TileView(mojo::ApplicationImpl* app_impl, 22 TileView::TileView(mojo::ApplicationImpl* app_impl,
12 const std::vector<std::string>& view_urls, 23 const std::vector<std::string>& view_urls,
13 const mojo::ui::ViewProvider::CreateViewCallback& callback) 24 const mojo::ui::ViewProvider::CreateViewCallback& callback)
14 : app_impl_(app_impl), 25 : BaseView(app_impl, "Tile", callback), view_urls_(view_urls) {
15 view_urls_(view_urls), 26 ConnectViews();
16 callback_(callback),
17 binding_(this),
18 surface_id_namespace_(0),
19 pending_child_layout_count_(0),
20 frame_pending_(false),
21 weak_ptr_factory_(this) {
22 app_impl_->ConnectToService("mojo:surfaces_service", &surfaces_);
23 app_impl_->ConnectToService("mojo:view_manager_service", &view_manager_);
24
25 surfaces_->GetIdNamespace(base::Bind(&TileView::OnSurfaceIdNamespaceAvailable,
26 base::Unretained(this)));
27 } 27 }
28 28
29 TileView::~TileView() {} 29 TileView::~TileView() {}
30 30
31 void TileView::OnSurfaceIdNamespaceAvailable(uint32_t id_namespace) { 31 void TileView::ConnectViews() {
32 surface_id_namespace_ = id_namespace;
33 InitView();
34 }
35
36 void TileView::InitView() {
37 // Register the view.
38 mojo::ui::ViewPtr view;
39 binding_.Bind(mojo::GetProxy(&view));
40 view_manager_->RegisterView(view.Pass(), mojo::GetProxy(&view_host_),
41 callback_);
42
43 // Connect to all child views.
44 uint32_t child_key = 0; 32 uint32_t child_key = 0;
45 for (const auto& url : view_urls_) { 33 for (const auto& url : view_urls_) {
46 // Start connecting to the view provider. 34 // Start connecting to the view provider.
47 mojo::ui::ViewProviderPtr provider; 35 mojo::ui::ViewProviderPtr provider;
48 app_impl_->ConnectToService(url, &provider); 36 app_impl()->ConnectToService(url, &provider);
49 provider.set_connection_error_handler( 37 provider.set_connection_error_handler(
50 base::Bind(&TileView::OnChildConnectionError, base::Unretained(this), 38 base::Bind(&TileView::OnChildConnectionError, base::Unretained(this),
51 child_key, url)); 39 child_key, url));
52 40
53 // Create the view. 41 // Create the view.
54 // We include the provider reference in the callback so that the 42 // We include the provider reference in the callback so that the
55 // binding will be kept alive until the callback completes. 43 // binding will be kept alive until the callback completes.
56 LOG(INFO) << "Connecting to view: child_key=" << child_key 44 LOG(INFO) << "Connecting to view: child_key=" << child_key
57 << ", url=" << url; 45 << ", url=" << url;
58 provider->CreateView( 46 provider->CreateView(
(...skipping 10 matching lines...) Expand all
69 << ", url=" << url; 57 << ", url=" << url;
70 } 58 }
71 59
72 void TileView::OnChildCreated(uint32_t child_key, 60 void TileView::OnChildCreated(uint32_t child_key,
73 const std::string& url, 61 const std::string& url,
74 mojo::ui::ViewProviderPtr provider, 62 mojo::ui::ViewProviderPtr provider,
75 mojo::ui::ViewTokenPtr token) { 63 mojo::ui::ViewTokenPtr token) {
76 DCHECK(views_.find(child_key) == views_.end()); 64 DCHECK(views_.find(child_key) == views_.end());
77 LOG(INFO) << "View created: child_key=" << child_key << ", url=" << url; 65 LOG(INFO) << "View created: child_key=" << child_key << ", url=" << url;
78 66
79 view_host_->AddChild(child_key, token.Pass()); 67 view_host()->AddChild(child_key, token.Pass());
80 views_.emplace( 68 views_.emplace(std::make_pair(
81 std::make_pair(child_key, std::unique_ptr<ViewData>(new ViewData(url)))); 69 child_key, std::unique_ptr<ViewData>(new ViewData(url, child_key))));
82 70
83 // Note that the view provider will be destroyed once this function 71 // Note that the view provider will be destroyed once this function
84 // returns which is fine now that we are done creating the view. 72 // returns which is fine now that we are done creating the view.
85 } 73 }
86 74
87 void TileView::OnChildUnavailable(uint32_t child_key, 75 void TileView::OnChildUnavailable(uint32_t child_key,
88 const OnChildUnavailableCallback& callback) { 76 const OnChildUnavailableCallback& callback) {
89 auto it = views_.find(child_key); 77 auto it = views_.find(child_key);
90 DCHECK(it != views_.end()); 78 DCHECK(it != views_.end());
91 LOG(ERROR) << "View died unexpectedly: child_key=" << child_key 79 LOG(ERROR) << "View died unexpectedly: child_key=" << child_key
92 << ", url=" << it->second->url; 80 << ", url=" << it->second->url;
93 81
94 std::unique_ptr<ViewData> view_data = std::move(it->second); 82 std::unique_ptr<ViewData> view_data = std::move(it->second);
95 views_.erase(it); 83 views_.erase(it);
96 84
97 view_host_->RemoveChild(child_key); 85 view_host()->RemoveChild(child_key);
98 86
99 if (view_data->layout_pending) { 87 if (view_data->layout_pending) {
100 DCHECK(pending_child_layout_count_); 88 DCHECK(pending_child_layout_count_);
101 pending_child_layout_count_--; 89 pending_child_layout_count_--;
102 FinishLayout(); 90 FinishLayout();
103 } 91 }
104 92
105 callback.Run(); 93 callback.Run();
106 } 94 }
107 95
108 void TileView::OnLayout(mojo::ui::ViewLayoutParamsPtr layout_params, 96 void TileView::OnLayout(mojo::ui::ViewLayoutParamsPtr layout_params,
109 mojo::Array<uint32_t> children_needing_layout, 97 mojo::Array<uint32_t> children_needing_layout,
110 const OnLayoutCallback& callback) { 98 const OnLayoutCallback& callback) {
111 // Create a new surface the first time or if the size has changed. 99 size_.width = layout_params->constraints->max_width;
112 mojo::Size new_size; 100 size_.height = layout_params->constraints->max_height;
113 new_size.width = layout_params->constraints->max_width;
114 new_size.height = layout_params->constraints->max_height;
115 if (!surface_id_ || !size_.Equals(new_size)) {
116 if (!surface_id_) {
117 surface_id_ = mojo::SurfaceId::New();
118 surface_id_->id_namespace = surface_id_namespace_;
119 } else {
120 surfaces_->DestroySurface(surface_id_->local);
121 }
122 surface_id_->local++;
123 size_ = new_size;
124 surfaces_->CreateSurface(surface_id_->local);
125 }
126 101
127 // Wipe out cached layout information for children needing layout. 102 // Wipe out cached layout information for children needing layout.
128 for (uint32_t child_key : children_needing_layout) { 103 for (uint32_t child_key : children_needing_layout) {
129 auto view_it = views_.find(child_key); 104 auto view_it = views_.find(child_key);
130 if (view_it != views_.end()) 105 if (view_it != views_.end())
131 view_it->second->layout_info.reset(); 106 view_it->second->layout_info.reset();
132 } 107 }
133 108
134 // Layout all children in a row. 109 // Layout all children in a row.
135 if (!views_.empty()) { 110 if (!views_.empty()) {
136 uint32_t index = 0; 111 uint32_t index = 0;
137 uint32_t base_width = new_size.width / views_.size(); 112 uint32_t base_width = size_.width / views_.size();
138 uint32_t excess_width = new_size.width % views_.size(); 113 uint32_t excess_width = size_.width % views_.size();
139 uint32_t x = 0; 114 uint32_t x = 0;
140 for (auto it = views_.begin(); it != views_.end(); ++it, ++index) { 115 for (auto it = views_.begin(); it != views_.end(); ++it, ++index) {
141 ViewData* view_data = it->second.get(); 116 ViewData* view_data = it->second.get();
142 DCHECK(!view_data->layout_pending); 117 DCHECK(!view_data->layout_pending);
143 118
144 // Distribute any excess width among the leading children. 119 // Distribute any excess width among the leading children.
145 uint32_t child_width = base_width; 120 uint32_t child_width = base_width;
146 if (excess_width) { 121 if (excess_width) {
147 child_width++; 122 child_width++;
148 excess_width--; 123 excess_width--;
149 } 124 }
150 uint32_t child_height = new_size.height; 125 uint32_t child_height = size_.height;
151 uint32_t child_x = x; 126 uint32_t child_x = x;
152 x += child_width; 127 x += child_width;
153 128
154 view_data->layout_bounds.x = child_x; 129 view_data->layout_bounds.x = child_x;
155 view_data->layout_bounds.y = 0; 130 view_data->layout_bounds.y = 0;
156 view_data->layout_bounds.width = child_width; 131 view_data->layout_bounds.width = child_width;
157 view_data->layout_bounds.height = child_height; 132 view_data->layout_bounds.height = child_height;
158 133
159 mojo::ui::ViewLayoutParamsPtr params = mojo::ui::ViewLayoutParams::New(); 134 mojo::ui::ViewLayoutParamsPtr params = mojo::ui::ViewLayoutParams::New();
160 params->constraints = mojo::ui::BoxConstraints::New(); 135 params->constraints = mojo::ui::BoxConstraints::New();
161 params->constraints->min_width = child_width; 136 params->constraints->min_width = child_width;
162 params->constraints->max_width = child_width; 137 params->constraints->max_width = child_width;
163 params->constraints->min_height = child_height; 138 params->constraints->min_height = child_height;
164 params->constraints->max_height = child_height; 139 params->constraints->max_height = child_height;
165 params->device_pixel_ratio = layout_params->device_pixel_ratio; 140 params->device_pixel_ratio = layout_params->device_pixel_ratio;
166 141
167 if (view_data->layout_info && view_data->layout_params.Equals(params)) 142 if (view_data->layout_info && view_data->layout_params.Equals(params))
168 continue; // no layout work to do 143 continue; // no layout work to do
169 144
170 pending_child_layout_count_++; 145 pending_child_layout_count_++;
171 view_data->layout_pending = true; 146 view_data->layout_pending = true;
172 view_data->layout_params = params.Clone(); 147 view_data->layout_params = params.Clone();
173 view_data->layout_info.reset(); 148 view_data->layout_info.reset();
174 149
175 view_host_->LayoutChild(it->first, params.Pass(), 150 view_host()->LayoutChild(it->first, params.Pass(),
176 base::Bind(&TileView::OnChildLayoutFinished, 151 base::Bind(&TileView::OnChildLayoutFinished,
177 base::Unretained(this), it->first)); 152 base::Unretained(this), it->first));
178 } 153 }
179 } 154 }
180 155
181 // Store the callback until layout of all children is finished. 156 // Store the callback until layout of all children is finished.
182 pending_layout_callback_ = callback; 157 pending_layout_callback_ = callback;
183 FinishLayout(); 158 FinishLayout();
184 } 159 }
185 160
186 void TileView::OnChildLayoutFinished( 161 void TileView::OnChildLayoutFinished(
187 uint32_t child_key, 162 uint32_t child_key,
188 mojo::ui::ViewLayoutInfoPtr child_layout_info) { 163 mojo::ui::ViewLayoutInfoPtr child_layout_info) {
189 auto it = views_.find(child_key); 164 auto it = views_.find(child_key);
190 if (it != views_.end()) { 165 if (it != views_.end()) {
191 ViewData* view_data = it->second.get(); 166 ViewData* view_data = it->second.get();
192 DCHECK(view_data->layout_pending); 167 DCHECK(view_data->layout_pending);
193 DCHECK(pending_child_layout_count_); 168 DCHECK(pending_child_layout_count_);
194 pending_child_layout_count_--; 169 pending_child_layout_count_--;
195 view_data->layout_pending = false; 170 view_data->layout_pending = false;
196 view_data->layout_info = child_layout_info.Pass(); 171 view_data->layout_info = child_layout_info.Pass();
197 FinishLayout(); 172 FinishLayout();
198 } 173 }
199 } 174 }
200 175
201 void TileView::FinishLayout() { 176 void TileView::FinishLayout() {
202 if (frame_pending_ || pending_layout_callback_.is_null()) 177 if (pending_layout_callback_.is_null())
203 return; 178 return;
204 179
205 // Wait until all children have laid out. 180 // Wait until all children have laid out.
206 // TODO(jeffbrown): There should be a timeout on this. 181 // TODO(jeffbrown): There should be a timeout on this.
207 if (pending_child_layout_count_) 182 if (pending_child_layout_count_)
208 return; 183 return;
209 184
210 // Produce a new frame. 185 // Update the scene.
211 mojo::FramePtr frame = mojo::Frame::New(); 186 // TODO: only send the resources once, be more incremental
212 frame->resources.resize(0u); 187 auto update = mojo::gfx::composition::SceneUpdate::New();
213 188
214 mojo::Rect bounds; 189 // Create the root node.
215 bounds.width = size_.width; 190 auto root_node = mojo::gfx::composition::Node::New();
216 bounds.height = size_.height;
217 mojo::PassPtr pass = mojo::CreateDefaultPass(1, bounds);
218 pass->shared_quad_states.resize(0u);
219 pass->quads.resize(0u);
220 191
192 // Add the children.
221 for (auto it = views_.cbegin(); it != views_.cend(); it++) { 193 for (auto it = views_.cbegin(); it != views_.cend(); it++) {
222 const ViewData& view_data = *(it->second.get()); 194 const ViewData& view_data = *(it->second.get());
195 const uint32_t scene_resource_id =
196 kViewResourceIdBase + view_data.key * kViewResourceIdSpacing;
197 const uint32_t container_node_id =
198 kViewNodeIdBase + view_data.key * kViewNodeIdSpacing;
199 const uint32_t scene_node_id = container_node_id + kViewSceneNodeIdOffset;
200 const uint32_t fallback_node_id =
201 container_node_id + kViewFallbackNodeIdOffset;
223 202
224 mojo::QuadPtr quad = mojo::Quad::New(); 203 mojo::Rect extent;
225 quad->rect = view_data.layout_bounds.Clone(); 204 extent.width = view_data.layout_bounds.width;
226 quad->rect->x = 0; 205 extent.height = view_data.layout_bounds.height;
227 quad->rect->y = 0;
228 quad->opaque_rect = quad->rect.Clone();
229 quad->visible_rect = quad->rect.Clone();
230 quad->shared_quad_state_index = pass->shared_quad_states.size();
231 206
232 mojo::Size size; 207 // Create a container to represent the place where the child view
233 size.width = view_data.layout_bounds.width; 208 // will be presented. The children of the container provide
234 size.height = view_data.layout_bounds.height; 209 // fallback behavior in case the view is not available.
210 auto container_node = mojo::gfx::composition::Node::New();
211 container_node->content_clip = extent.Clone();
212 container_node->content_transform = mojo::Transform::New();
213 SetTranslationTransform(container_node->content_transform.get(),
214 view_data.layout_bounds.x,
215 view_data.layout_bounds.y, 0.f);
216 container_node->combinator =
217 mojo::gfx::composition::Node::Combinator::FALLBACK;
235 218
236 mojo::SharedQuadStatePtr quad_state = mojo::CreateDefaultSQS(size); 219 // If we have the view, add it to the scene.
237 quad_state->content_to_target_transform->matrix[3] = 220 if (view_data.layout_info) {
238 view_data.layout_bounds.x; 221 auto scene_resource = mojo::gfx::composition::Resource::New();
239 pass->shared_quad_states.push_back(quad_state.Pass()); 222 scene_resource->set_scene(mojo::gfx::composition::SceneResource::New());
223 scene_resource->get_scene()->scene_token =
224 view_data.layout_info->scene_token.Clone();
225 update->resources.insert(scene_resource_id, scene_resource.Pass());
240 226
241 if (it->second->layout_info) { 227 auto scene_node = mojo::gfx::composition::Node::New();
242 quad->material = mojo::Material::SURFACE_CONTENT; 228 scene_node->op = mojo::gfx::composition::NodeOp::New();
243 quad->surface_quad_state = mojo::SurfaceQuadState::New(); 229 scene_node->op->set_scene(mojo::gfx::composition::SceneNodeOp::New());
244 quad->surface_quad_state->surface = 230 scene_node->op->get_scene()->scene_resource_id = scene_resource_id;
245 view_data.layout_info->surface_id.Clone(); 231 update->nodes.insert(scene_node_id, scene_node.Pass());
232 container_node->child_node_ids.push_back(scene_node_id);
246 } else { 233 } else {
247 quad->material = mojo::Material::SOLID_COLOR; 234 update->resources.insert(fallback_node_id, nullptr);
248 quad->solid_color_quad_state = mojo::SolidColorQuadState::New(); 235 update->nodes.insert(scene_node_id, nullptr);
249 quad->solid_color_quad_state->color = mojo::Color::New();
250 quad->solid_color_quad_state->color->rgba = 0xffff00ff;
251 } 236 }
252 237
253 pass->quads.push_back(quad.Pass()); 238 // Add the fallback content.
239 auto fallback_node = mojo::gfx::composition::Node::New();
240 fallback_node->op = mojo::gfx::composition::NodeOp::New();
241 fallback_node->op->set_rect(mojo::gfx::composition::RectNodeOp::New());
242 fallback_node->op->get_rect()->content_rect = extent.Clone();
243 fallback_node->op->get_rect()->color = mojo::gfx::composition::Color::New();
244 fallback_node->op->get_rect()->color->red = 255;
245 fallback_node->op->get_rect()->color->alpha = 255;
246 update->nodes.insert(fallback_node_id, fallback_node.Pass());
247 container_node->child_node_ids.push_back(fallback_node_id);
248
249 // Add the container.
250 update->nodes.insert(container_node_id, container_node.Pass());
251 root_node->child_node_ids.push_back(container_node_id);
254 } 252 }
255 253
256 frame->passes.push_back(pass.Pass()); 254 // Add the root node.
255 update->nodes.insert(kRootNodeId, root_node.Pass());
257 256
258 frame_pending_ = true; 257 // Publish the scene.
259 surfaces_->SubmitFrame( 258 scene()->Update(update.Pass());
260 surface_id_->local, frame.Pass(), 259 scene()->Publish(nullptr);
261 base::Bind(&TileView::OnFrameSubmitted, base::Unretained(this)));
262 260
263 // Submit the new layout information. 261 // Submit the new layout information.
264 mojo::ui::ViewLayoutInfoPtr info = mojo::ui::ViewLayoutInfo::New(); 262 auto info = mojo::ui::ViewLayoutResult::New();
265 info->size = size_.Clone(); 263 info->size = size_.Clone();
266 info->surface_id = surface_id_->Clone();
267 pending_layout_callback_.Run(info.Pass()); 264 pending_layout_callback_.Run(info.Pass());
268 pending_layout_callback_.reset(); 265 pending_layout_callback_.reset();
269 } 266 }
270 267
271 void TileView::OnFrameSubmitted() { 268 TileView::ViewData::ViewData(const std::string& url, uint32_t key)
272 DCHECK(frame_pending_); 269 : url(url), key(key), layout_pending(false) {}
273
274 frame_pending_ = false;
275 FinishLayout();
276 }
277
278 TileView::ViewData::ViewData(const std::string& url)
279 : url(url), layout_pending(false) {}
280 270
281 TileView::ViewData::~ViewData() {} 271 TileView::ViewData::~ViewData() {}
282 272
283 } // namespace examples 273 } // namespace examples
OLDNEW
« no previous file with comments | « examples/ui/tile/tile_view.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698