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

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: Created 5 years, 2 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
« examples/ui/tile/tile_app.cc ('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 <algorithm>
6
7 #include "examples/ui/tile/tile_view.h"
8 #include "mojo/services/surfaces/cpp/surfaces_utils.h"
9 #include "mojo/services/surfaces/interfaces/quads.mojom.h"
10
11 namespace examples {
12
13 TileView::TileView(mojo::ApplicationImpl* app_impl,
14 const std::vector<std::string>& view_urls,
15 const mojo::ui::ViewProvider::CreateViewCallback& callback)
16 : app_impl_(app_impl),
17 view_urls_(view_urls),
18 callback_(callback),
19 binding_(this),
20 surface_id_namespace_(0),
21 frame_pending_(false),
22 weak_ptr_factory_(this) {
23 app_impl_->ConnectToService("mojo:surfaces_service", &surfaces_);
24 app_impl_->ConnectToService("mojo:view_manager_service", &view_manager_);
25
26 surfaces_->GetIdNamespace(base::Bind(&TileView::OnSurfaceIdNamespaceAvailable,
27 base::Unretained(this)));
28 }
29
30 TileView::~TileView() {}
31
32 void TileView::OnSurfaceIdNamespaceAvailable(uint32_t id_namespace) {
33 surface_id_namespace_ = id_namespace;
34 InitView();
35 }
36
37 void TileView::InitView() {
38 // Register the view.
39 mojo::ui::ViewPtr view;
40 binding_.Bind(mojo::GetProxy(&view));
41 view_manager_->RegisterView(view.Pass(), mojo::GetProxy(&view_host_),
42 callback_);
43
44 // Connect to all child views.
45 for (auto it = view_urls_.begin(); it != view_urls_.end(); it++) {
abarth 2015/10/24 06:51:12 for (const std::string& url : view_urls_) {
46 const std::string& url = *it;
47 const uint32_t key = it - view_urls_.begin();
abarth 2015/10/24 06:51:12 Oh, I see... I probably would have just used the
jeffbrown 2015/10/27 03:13:08 Honestly I just didn't know the for iterator synta
48
49 // Start connecting to the view provider.
50 mojo::ui::ViewProviderPtr provider;
51 app_impl_->ConnectToService(url, &provider);
52 provider.set_connection_error_handler(base::Bind(
53 &TileView::OnChildConnectionError, base::Unretained(this), key, url));
54
55 // Create the view.
56 // We include the provider reference in the callback so that the
57 // binding will be kept alive until the callback completes.
58 LOG(INFO) << "Connecting to view: key=" << key << ", url=" << url;
59 provider->CreateView(
60 mojo::InterfaceRequest<mojo::ServiceProvider>(),
abarth 2015/10/24 06:51:12 there's no implicit conversion from |nullptr| ?
jamesr 2015/10/26 20:31:21 there is. provider->CreateView(nullptr, nullptr, .
jeffbrown 2015/10/27 03:13:08 Done.
61 mojo::ServiceProviderPtr(),
abarth 2015/10/24 06:51:12 ditto
62 base::Bind(&TileView::OnChildCreated, base::Unretained(this), key, url,
63 base::Passed(provider.Pass())));
64 }
65 }
66
67 void TileView::OnChildConnectionError(uint32_t child_key,
68 const std::string& url) {
69 LOG(ERROR) << "Could not connect to view: key=" << child_key
70 << ", url=" << url;
71 }
72
73 void TileView::OnChildCreated(uint32_t child_key,
74 const std::string& url,
75 mojo::ui::ViewProviderPtr provider,
76 mojo::ui::ViewTokenPtr token) {
77 DCHECK(views_.find(child_key) == views_.end());
78
79 LOG(INFO) << "View created: key=" << child_key << ", url=" << url;
80 view_host_->AddChild(child_key, token.Pass());
81 views_.emplace(
82 std::make_pair(child_key, std::unique_ptr<ViewData>(new ViewData(url))));
abarth 2015/10/24 06:51:12 We don't have std::make_unique<ViewData>(url) but
jamesr 2015/10/26 20:31:21 there's this: https://github.com/domokit/mojo/blo
jeffbrown 2015/10/27 03:13:08 Hardly seems worth it here. I think I'll just lea
83
84 // Don't need the view provider anymore now that we have created the view
85 // so stop watching for errors.
86 provider.set_connection_error_handler(base::Closure());
87 }
88
89 void TileView::OnChildUnavailable(uint32_t child_key,
90 const OnChildUnavailableCallback& callback) {
91 auto it = views_.find(child_key);
92 DCHECK(it != views_.end());
93
94 LOG(ERROR) << "View died unexpectedly: key=" << child_key
95 << ", url=" << it->second->url();
96 view_host_->RemoveChild(child_key);
97 views_.erase(it);
98 FinishLayout();
99
100 callback.Run();
101 }
102
103 void TileView::OnLayout(mojo::ui::ViewLayoutParamsPtr layout_params,
104 mojo::Array<uint32_t> children_needing_layout,
105 const OnLayoutCallback& callback) {
106 // Create a new surface the first time or if the size has changed.
107 mojo::Size new_size;
108 new_size.width = layout_params->constraints->max_width;
109 new_size.height = layout_params->constraints->max_height;
110 if (!surface_id_ || !size_.Equals(new_size)) {
111 if (!surface_id_) {
112 surface_id_ = mojo::SurfaceId::New();
113 surface_id_->id_namespace = surface_id_namespace_;
114 } else {
115 surfaces_->DestroySurface(surface_id_->local);
116 }
117 surface_id_->local++;
118 size_ = new_size;
119 surfaces_->CreateSurface(surface_id_->local);
120 }
abarth 2015/10/24 06:51:12 This stanza has come up several times now...
jeffbrown 2015/10/27 03:13:08 Yup. I find it helpful to be explicit in example
121
122 // Wipe out cached layout information for children needing layout.
123 for (auto it = children_needing_layout.begin();
124 it != children_needing_layout.end(); ++it) {
abarth 2015/10/24 06:51:12 for (uint32_t id : children_needing_layout) {
125 auto view_it = views_.find(*it);
126 if (view_it != views_.end())
127 view_it->second->layout_info.reset();
128 }
129
130 // Layout all children in a row.
131 uint32_t index = 0;
132 for (auto it = views_.begin(); it != views_.end(); ++it, ++index) {
133 ViewData* view_data = it->second.get();
134 DCHECK(!view_data->layout_pending);
135
136 uint32_t child_width = new_size.width / views_.size();
abarth 2015/10/24 06:51:12 If new_size.width doesn't divide evenly by views_.
jeffbrown 2015/10/27 03:13:08 Good point!
137 uint32_t child_height = new_size.height;
138
139 mojo::ui::ViewLayoutParamsPtr params = mojo::ui::ViewLayoutParams::New();
140 params->constraints = mojo::ui::BoxConstraints::New();
141 params->constraints->min_width = child_width;
142 params->constraints->max_width = child_width;
143 params->constraints->min_height = child_height;
144 params->constraints->max_height = child_height;
145 params->device_pixel_ratio = layout_params->device_pixel_ratio;
abarth 2015/10/24 06:51:12 This would be more future-proof if you made |param
jeffbrown 2015/10/27 03:13:08 Discussed in person. I'll see about pushing more
146
147 if (view_data->layout_info.get() && view_data->layout_params.Equals(params))
148 continue; // no work to do
abarth 2015/10/24 06:51:12 This seems dubious. What if one of our grandchild
jeffbrown 2015/10/27 03:13:08 This is just an optimization to avoid an extra rou
149
150 view_data->layout_pending = true;
151 view_data->layout_params = params.Clone();
152 view_data->layout_info.reset();
153 view_data->layout_bounds.x = child_width * index;
154 view_data->layout_bounds.y = 0;
155 view_data->layout_bounds.width = child_width;
156 view_data->layout_bounds.height = child_height;
157
158 view_host_->LayoutChild(it->first, params.Pass(), false /*provide_size*/,
159 base::Bind(&TileView::OnChildLayoutFinished,
160 base::Unretained(this), it->first));
161 }
162
163 // Store the callback until layout of all children is finished.
164 pending_layout_callback_ = callback;
165 FinishLayout();
166 }
167
168 void TileView::OnChildLayoutFinished(
169 uint32_t child_key,
170 mojo::ui::ViewLayoutInfoPtr child_layout_info) {
171 auto it = views_.find(child_key);
172 if (it != views_.end()) {
173 it->second->layout_pending = false;
174 it->second->layout_info = child_layout_info.Pass();
175 FinishLayout();
176 }
177 }
178
179 void TileView::FinishLayout() {
180 if (frame_pending_ || pending_layout_callback_.is_null())
181 return;
182
183 // Wait until all children have laid out.
184 // TODO(jeffbrown): There should be a timeout on this.
185 if (std::any_of(views_.begin(), views_.end(),
jamesr 2015/10/26 20:31:21 this scales linearly with views, which might be a
jeffbrown 2015/10/27 03:13:08 True. This is simpler (state can't get out of syn
186 [](const decltype(views_)::value_type& pair) {
jamesr 2015/10/26 20:31:21 this is an odd use of decltype, imo. this isn't ge
jeffbrown 2015/10/27 03:13:08 Hmm. I think the intention is pretty clear. I do
187 return pair.second->layout_pending;
188 }))
189 return;
190
191 // Produce a new frame.
abarth 2015/10/24 06:51:12 This system would be cleaner if the parent allocat
jeffbrown 2015/10/27 03:13:08 It might be. Depends on whether a new surface is
192 mojo::FramePtr frame = mojo::Frame::New();
193 frame->resources.resize(0u);
jamesr 2015/10/26 20:31:21 i *hate* that mojo arrays are nullable - the fact
jeffbrown 2015/10/27 03:13:08 Yup. It's nuts. And if I omit this line then the
194
195 mojo::Rect bounds;
196 bounds.width = size_.width;
197 bounds.height = size_.height;
198 mojo::PassPtr pass = mojo::CreateDefaultPass(1, bounds);
199 pass->shared_quad_states.resize(0u);
200 pass->quads.resize(0u);
201
202 for (auto it = views_.begin(); it != views_.end(); it++) {
jamesr 2015/10/26 20:31:21 'const auto& it' ?
203 const ViewData* view_data = it->second.get();
jamesr 2015/10/26 20:31:21 const ViewData& view_data ? it's not useful to nul
jeffbrown 2015/10/27 03:13:08 Sure, why not.
204
205 mojo::QuadPtr quad = mojo::Quad::New();
206 quad->rect = view_data->layout_bounds.Clone();
207 quad->rect->x = 0;
208 quad->rect->y = 0;
209 quad->opaque_rect = quad->rect.Clone();
210 quad->visible_rect = quad->rect.Clone();
211 quad->shared_quad_state_index = pass->shared_quad_states.size();
212
213 mojo::Size size;
214 size.width = view_data->layout_bounds.width;
215 size.height = view_data->layout_bounds.height;
216
217 mojo::SharedQuadStatePtr quad_state = mojo::CreateDefaultSQS(size);
218 quad_state->content_to_target_transform->matrix[3] =
219 view_data->layout_bounds.x;
220 pass->shared_quad_states.push_back(quad_state.Pass());
221
222 if (it->second->layout_info.get()) {
223 quad->material = mojo::Material::SURFACE_CONTENT;
224 quad->surface_quad_state = mojo::SurfaceQuadState::New();
225 quad->surface_quad_state->surface =
226 view_data->layout_info->surface_id.Clone();
227 } else {
228 quad->material = mojo::Material::SOLID_COLOR;
229 quad->solid_color_quad_state = mojo::SolidColorQuadState::New();
230 quad->solid_color_quad_state->color = mojo::Color::New();
231 quad->solid_color_quad_state->color->rgba = 0xffff00ff;
jamesr 2015/10/26 20:31:21 i think we have some named colors somewhere (not t
232 }
233
234 pass->quads.push_back(quad.Pass());
235 }
236
237 frame->passes.push_back(pass.Pass());
238
239 frame_pending_ = true;
240 surfaces_->SubmitFrame(
241 surface_id_->local, frame.Pass(),
242 base::Bind(&TileView::OnFrameSubmitted, base::Unretained(this)));
243
244 // Submit the new layout information.
245 mojo::ui::ViewLayoutInfoPtr info = mojo::ui::ViewLayoutInfo::New();
246 info->size = size_.Clone();
247 info->surface_id = surface_id_->Clone();
248 pending_layout_callback_.Run(info.Pass());
249 pending_layout_callback_.reset();
250 }
251
252 void TileView::OnFrameSubmitted() {
253 DCHECK(frame_pending_);
254
255 frame_pending_ = false;
256 FinishLayout();
257 }
258
259 TileView::ViewData::ViewData(const std::string& url)
260 : layout_pending(false), url_(url) {}
261
262 TileView::ViewData::~ViewData() {}
263
264 } // namespace examples
OLDNEW
« examples/ui/tile/tile_app.cc ('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