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

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

Issue 1425543002: mozart: Add a simple tiling view manager. (Closed) Base URL: git@github.com:domokit/mojo.git@master
Patch Set: apply review comments Created 5 years, 1 month 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
« examples/ui/tile/tile_view.h ('K') | « 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
(Empty)
1 // Copyright 2013 The Chromium 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 "examples/ui/tile/tile_view.h"
6 #include "mojo/services/surfaces/cpp/surfaces_utils.h"
7 #include "mojo/services/surfaces/interfaces/quads.mojom.h"
8
9 namespace examples {
10
11 TileView::TileView(mojo::ApplicationImpl* app_impl,
12 const std::vector<std::string>& view_urls,
13 const mojo::ui::ViewProvider::CreateViewCallback& callback)
14 : app_impl_(app_impl),
15 view_urls_(view_urls),
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 }
28
29 TileView::~TileView() {}
30
31 void TileView::OnSurfaceIdNamespaceAvailable(uint32_t id_namespace) {
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;
45 for (auto url : view_urls_) {
qsr 2015/10/27 09:01:27 const auto& ?
jeffbrown 2015/10/27 22:54:24 Done.
46 // Start connecting to the view provider.
47 mojo::ui::ViewProviderPtr provider;
48 app_impl_->ConnectToService(url, &provider);
49 provider.set_connection_error_handler(
50 base::Bind(&TileView::OnChildConnectionError, base::Unretained(this),
51 child_key, url));
52
53 // Create the view.
54 // We include the provider reference in the callback so that the
55 // binding will be kept alive until the callback completes.
56 LOG(INFO) << "Connecting to view: child_key=" << child_key
57 << ", url=" << url;
58 provider->CreateView(
59 nullptr, nullptr,
60 base::Bind(&TileView::OnChildCreated, base::Unretained(this), child_key,
61 url, base::Passed(provider.Pass())));
62 child_key++;
63 }
64 }
65
66 void TileView::OnChildConnectionError(uint32_t child_key,
67 const std::string& url) {
68 LOG(ERROR) << "Could not connect to view: child_key=" << child_key
69 << ", url=" << url;
70 }
71
72 void TileView::OnChildCreated(uint32_t child_key,
73 const std::string& url,
74 mojo::ui::ViewProviderPtr provider,
75 mojo::ui::ViewTokenPtr token) {
76 DCHECK(views_.find(child_key) == views_.end());
77 LOG(INFO) << "View created: child_key=" << child_key << ", url=" << url;
78
79 view_host_->AddChild(child_key, token.Pass());
80 views_.emplace(
81 std::make_pair(child_key, std::unique_ptr<ViewData>(new ViewData(url))));
jamesr 2015/10/27 22:58:27 there's a school of thought that C++ code using sm
jeffbrown 2015/10/27 23:24:19 Feels weird to depend on an EDK header here so I'l
82
83 // Don't need the view provider anymore now that we have created the view
84 // so stop watching for errors.
85 provider.set_connection_error_handler(base::Closure());
qsr 2015/10/27 09:01:27 Why is this needed? The provider will be deleted a
jeffbrown 2015/10/27 22:54:24 Good point, this is redundant.
86 }
87
88 void TileView::OnChildUnavailable(uint32_t child_key,
89 const OnChildUnavailableCallback& callback) {
90 auto it = views_.find(child_key);
91 DCHECK(it != views_.end());
92 LOG(ERROR) << "View died unexpectedly: child_key=" << child_key
93 << ", url=" << it->second->url();
94
95 std::unique_ptr<ViewData> view_data = std::move(it->second);
96 views_.erase(it);
97
98 view_host_->RemoveChild(child_key);
99
100 if (view_data->layout_pending) {
101 DCHECK(pending_child_layout_count_);
102 pending_child_layout_count_--;
103 FinishLayout();
104 }
105
106 callback.Run();
107 }
108
109 void TileView::OnLayout(mojo::ui::ViewLayoutParamsPtr layout_params,
110 mojo::Array<uint32_t> children_needing_layout,
111 const OnLayoutCallback& callback) {
112 // Create a new surface the first time or if the size has changed.
113 mojo::Size new_size;
114 new_size.width = layout_params->constraints->max_width;
115 new_size.height = layout_params->constraints->max_height;
116 if (!surface_id_ || !size_.Equals(new_size)) {
117 if (!surface_id_) {
118 surface_id_ = mojo::SurfaceId::New();
119 surface_id_->id_namespace = surface_id_namespace_;
120 } else {
121 surfaces_->DestroySurface(surface_id_->local);
122 }
123 surface_id_->local++;
124 size_ = new_size;
125 surfaces_->CreateSurface(surface_id_->local);
126 }
127
128 // Wipe out cached layout information for children needing layout.
129 for (uint32_t child_key : children_needing_layout) {
130 auto view_it = views_.find(child_key);
131 if (view_it != views_.end())
132 view_it->second->layout_info.reset();
133 }
134
135 // Layout all children in a row.
136 if (!views_.empty()) {
137 uint32_t index = 0;
138 uint32_t base_width = new_size.width / views_.size();
139 uint32_t excess_width = new_size.width % views_.size();
140 uint32_t x = 0;
141 for (auto it = views_.begin(); it != views_.end(); ++it, ++index) {
142 ViewData* view_data = it->second.get();
143 DCHECK(!view_data->layout_pending);
144
145 // Distribute any excess width among the leading children.
146 uint32_t child_width = base_width;
147 if (excess_width) {
148 child_width++;
149 excess_width--;
150 }
151 uint32_t child_height = new_size.height;
152 uint32_t child_x = x;
153 x += child_width;
154
155 view_data->layout_bounds.x = child_x;
156 view_data->layout_bounds.y = 0;
157 view_data->layout_bounds.width = child_width;
158 view_data->layout_bounds.height = child_height;
159
160 mojo::ui::ViewLayoutParamsPtr params = mojo::ui::ViewLayoutParams::New();
161 params->constraints = mojo::ui::BoxConstraints::New();
162 params->constraints->min_width = child_width;
163 params->constraints->max_width = child_width;
164 params->constraints->min_height = child_height;
165 params->constraints->max_height = child_height;
166 params->device_pixel_ratio = layout_params->device_pixel_ratio;
167
168 if (view_data->layout_info && view_data->layout_params.Equals(params))
169 continue; // no layout work to do
170
171 pending_child_layout_count_++;
172 view_data->layout_pending = true;
173 view_data->layout_params = params.Clone();
174 view_data->layout_info.reset();
175
176 view_host_->LayoutChild(it->first, params.Pass(),
177 base::Bind(&TileView::OnChildLayoutFinished,
178 base::Unretained(this), it->first));
179 }
180 }
181
182 // Store the callback until layout of all children is finished.
183 pending_layout_callback_ = callback;
184 FinishLayout();
185 }
186
187 void TileView::OnChildLayoutFinished(
188 uint32_t child_key,
189 mojo::ui::ViewLayoutInfoPtr child_layout_info) {
190 auto it = views_.find(child_key);
191 if (it != views_.end()) {
192 ViewData* view_data = it->second.get();
193 DCHECK(view_data->layout_pending);
194 DCHECK(pending_child_layout_count_);
195 pending_child_layout_count_--;
196 view_data->layout_pending = false;
197 view_data->layout_info = child_layout_info.Pass();
198 FinishLayout();
199 }
200 }
201
202 void TileView::FinishLayout() {
203 if (frame_pending_ || pending_layout_callback_.is_null())
204 return;
205
206 // Wait until all children have laid out.
207 // TODO(jeffbrown): There should be a timeout on this.
208 if (pending_child_layout_count_)
209 return;
210
211 // Produce a new frame.
212 mojo::FramePtr frame = mojo::Frame::New();
213 frame->resources.resize(0u);
214
215 mojo::Rect bounds;
216 bounds.width = size_.width;
217 bounds.height = size_.height;
218 mojo::PassPtr pass = mojo::CreateDefaultPass(1, bounds);
219 pass->shared_quad_states.resize(0u);
220 pass->quads.resize(0u);
221
222 for (auto it = views_.cbegin(); it != views_.cend(); it++) {
223 const ViewData& view_data = *(it->second.get());
224
225 mojo::QuadPtr quad = mojo::Quad::New();
226 quad->rect = view_data.layout_bounds.Clone();
227 quad->rect->x = 0;
228 quad->rect->y = 0;
229 quad->opaque_rect = quad->rect.Clone();
230 quad->visible_rect = quad->rect.Clone();
231 quad->shared_quad_state_index = pass->shared_quad_states.size();
232
233 mojo::Size size;
234 size.width = view_data.layout_bounds.width;
235 size.height = view_data.layout_bounds.height;
236
237 mojo::SharedQuadStatePtr quad_state = mojo::CreateDefaultSQS(size);
238 quad_state->content_to_target_transform->matrix[3] =
239 view_data.layout_bounds.x;
240 pass->shared_quad_states.push_back(quad_state.Pass());
241
242 if (it->second->layout_info) {
243 quad->material = mojo::Material::SURFACE_CONTENT;
244 quad->surface_quad_state = mojo::SurfaceQuadState::New();
245 quad->surface_quad_state->surface =
246 view_data.layout_info->surface_id.Clone();
247 } else {
248 quad->material = mojo::Material::SOLID_COLOR;
249 quad->solid_color_quad_state = mojo::SolidColorQuadState::New();
250 quad->solid_color_quad_state->color = mojo::Color::New();
251 quad->solid_color_quad_state->color->rgba = 0xffff00ff;
252 }
253
254 pass->quads.push_back(quad.Pass());
255 }
256
257 frame->passes.push_back(pass.Pass());
258
259 frame_pending_ = true;
260 surfaces_->SubmitFrame(
261 surface_id_->local, frame.Pass(),
262 base::Bind(&TileView::OnFrameSubmitted, base::Unretained(this)));
263
264 // Submit the new layout information.
265 mojo::ui::ViewLayoutInfoPtr info = mojo::ui::ViewLayoutInfo::New();
266 info->size = size_.Clone();
267 info->surface_id = surface_id_->Clone();
268 pending_layout_callback_.Run(info.Pass());
269 pending_layout_callback_.reset();
270 }
271
272 void TileView::OnFrameSubmitted() {
273 DCHECK(frame_pending_);
274
275 frame_pending_ = false;
276 FinishLayout();
277 }
278
279 TileView::ViewData::ViewData(const std::string& url)
280 : layout_pending(false), url_(url) {}
281
282 TileView::ViewData::~ViewData() {}
283
284 } // namespace examples
OLDNEW
« examples/ui/tile/tile_view.h ('K') | « examples/ui/tile/tile_view.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698