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

Side by Side Diff: components/view_manager/public/cpp/lib/view_tree_client_impl.cc

Issue 1344573002: Mandoline: Rename components/view_manager to components/mus (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Rebased Created 5 years, 3 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
OLDNEW
(Empty)
1 // Copyright 2014 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 "components/view_manager/public/cpp/lib/view_tree_client_impl.h"
6
7 #include "components/view_manager/public/cpp/lib/view_private.h"
8 #include "components/view_manager/public/cpp/util.h"
9 #include "components/view_manager/public/cpp/view_observer.h"
10 #include "components/view_manager/public/cpp/view_tree_connection.h"
11 #include "components/view_manager/public/cpp/view_tree_delegate.h"
12 #include "mojo/application/public/cpp/application_impl.h"
13 #include "mojo/application/public/cpp/connect.h"
14 #include "mojo/application/public/cpp/service_provider_impl.h"
15 #include "mojo/application/public/interfaces/service_provider.mojom.h"
16
17 namespace mojo {
18
19 Id MakeTransportId(ConnectionSpecificId connection_id,
20 ConnectionSpecificId local_id) {
21 return (connection_id << 16) | local_id;
22 }
23
24 // Helper called to construct a local view object from transport data.
25 View* AddViewToConnection(ViewTreeClientImpl* client,
26 View* parent,
27 const ViewDataPtr& view_data) {
28 // We don't use the cto that takes a ViewTreeConnection here, since it will
29 // call back to the service and attempt to create a new view.
30 View* view = ViewPrivate::LocalCreate();
31 ViewPrivate private_view(view);
32 private_view.set_connection(client);
33 private_view.set_id(view_data->view_id);
34 private_view.set_visible(view_data->visible);
35 private_view.set_drawn(view_data->drawn);
36 private_view.LocalSetViewportMetrics(ViewportMetrics(),
37 *view_data->viewport_metrics);
38 private_view.set_properties(
39 view_data->properties.To<std::map<std::string, std::vector<uint8_t>>>());
40 client->AddView(view);
41 private_view.LocalSetBounds(Rect(), *view_data->bounds);
42 if (parent)
43 ViewPrivate(parent).LocalAddChild(view);
44 return view;
45 }
46
47 View* BuildViewTree(ViewTreeClientImpl* client,
48 const Array<ViewDataPtr>& views,
49 View* initial_parent) {
50 std::vector<View*> parents;
51 View* root = NULL;
52 View* last_view = NULL;
53 if (initial_parent)
54 parents.push_back(initial_parent);
55 for (size_t i = 0; i < views.size(); ++i) {
56 if (last_view && views[i]->parent_id == last_view->id()) {
57 parents.push_back(last_view);
58 } else if (!parents.empty()) {
59 while (parents.back()->id() != views[i]->parent_id)
60 parents.pop_back();
61 }
62 View* view = AddViewToConnection(
63 client, !parents.empty() ? parents.back() : NULL, views[i]);
64 if (!last_view)
65 root = view;
66 last_view = view;
67 }
68 return root;
69 }
70
71 ViewTreeConnection* ViewTreeConnection::Create(
72 ViewTreeDelegate* delegate,
73 InterfaceRequest<ViewTreeClient> request) {
74 return new ViewTreeClientImpl(delegate, request.Pass());
75 }
76
77 ViewTreeClientImpl::ViewTreeClientImpl(
78 ViewTreeDelegate* delegate,
79 InterfaceRequest<ViewTreeClient> request)
80 : connection_id_(0),
81 next_id_(1),
82 delegate_(delegate),
83 root_(nullptr),
84 capture_view_(nullptr),
85 focused_view_(nullptr),
86 activated_view_(nullptr),
87 binding_(this, request.Pass()),
88 is_embed_root_(false),
89 in_destructor_(false) {
90 }
91
92 ViewTreeClientImpl::~ViewTreeClientImpl() {
93 in_destructor_ = true;
94
95 std::vector<View*> non_owned;
96 while (!views_.empty()) {
97 IdToViewMap::iterator it = views_.begin();
98 if (OwnsView(it->second->id())) {
99 it->second->Destroy();
100 } else {
101 non_owned.push_back(it->second);
102 views_.erase(it);
103 }
104 }
105
106 // Delete the non-owned views last. In the typical case these are roots. The
107 // exception is the window manager and embed roots, which may know about
108 // other random views that it doesn't own.
109 // NOTE: we manually delete as we're a friend.
110 for (size_t i = 0; i < non_owned.size(); ++i)
111 delete non_owned[i];
112
113 delegate_->OnConnectionLost(this);
114 }
115
116 void ViewTreeClientImpl::DestroyView(Id view_id) {
117 DCHECK(tree_);
118 tree_->DeleteView(view_id, ActionCompletedCallback());
119 }
120
121 void ViewTreeClientImpl::AddChild(Id child_id, Id parent_id) {
122 DCHECK(tree_);
123 tree_->AddView(parent_id, child_id, ActionCompletedCallback());
124 }
125
126 void ViewTreeClientImpl::RemoveChild(Id child_id, Id parent_id) {
127 DCHECK(tree_);
128 tree_->RemoveViewFromParent(child_id, ActionCompletedCallback());
129 }
130
131 void ViewTreeClientImpl::Reorder(
132 Id view_id,
133 Id relative_view_id,
134 OrderDirection direction) {
135 DCHECK(tree_);
136 tree_->ReorderView(view_id, relative_view_id, direction,
137 ActionCompletedCallback());
138 }
139
140 bool ViewTreeClientImpl::OwnsView(Id id) const {
141 return HiWord(id) == connection_id_;
142 }
143
144 void ViewTreeClientImpl::SetBounds(Id view_id, const Rect& bounds) {
145 DCHECK(tree_);
146 tree_->SetViewBounds(view_id, bounds.Clone(), ActionCompletedCallback());
147 }
148
149 void ViewTreeClientImpl::SetFocus(Id view_id) {
150 // In order for us to get here we had to have exposed a view, which implies we
151 // got a connection.
152 DCHECK(tree_);
153 tree_->SetFocus(view_id);
154 }
155
156 void ViewTreeClientImpl::SetVisible(Id view_id, bool visible) {
157 DCHECK(tree_);
158 tree_->SetViewVisibility(view_id, visible, ActionCompletedCallback());
159 }
160
161 void ViewTreeClientImpl::SetProperty(
162 Id view_id,
163 const std::string& name,
164 const std::vector<uint8_t>& data) {
165 DCHECK(tree_);
166 tree_->SetViewProperty(view_id,
167 String(name),
168 Array<uint8_t>::From(data),
169 ActionCompletedCallback());
170 }
171
172 void ViewTreeClientImpl::SetViewTextInputState(Id view_id,
173 TextInputStatePtr state) {
174 DCHECK(tree_);
175 tree_->SetViewTextInputState(view_id, state.Pass());
176 }
177
178 void ViewTreeClientImpl::SetImeVisibility(Id view_id,
179 bool visible,
180 TextInputStatePtr state) {
181 DCHECK(tree_);
182 tree_->SetImeVisibility(view_id, visible, state.Pass());
183 }
184
185 void ViewTreeClientImpl::SetAccessPolicy(Id view_id, uint32_t access_policy) {
186 DCHECK(tree_);
187 tree_->SetAccessPolicy(view_id, access_policy);
188 }
189
190 void ViewTreeClientImpl::Embed(Id view_id,
191 ViewTreeClientPtr client,
192 const ViewTree::EmbedCallback& callback) {
193 DCHECK(tree_);
194 tree_->Embed(view_id, client.Pass(), callback);
195 }
196
197 void ViewTreeClientImpl::RequestSurface(Id view_id,
198 InterfaceRequest<Surface> surface,
199 SurfaceClientPtr client) {
200 DCHECK(tree_);
201 tree_->RequestSurface(view_id, surface.Pass(), client.Pass());
202 }
203
204 void ViewTreeClientImpl::AddView(View* view) {
205 DCHECK(views_.find(view->id()) == views_.end());
206 views_[view->id()] = view;
207 }
208
209 void ViewTreeClientImpl::RemoveView(Id view_id) {
210 if (focused_view_ && focused_view_->id() == view_id)
211 OnViewFocused(0);
212
213 IdToViewMap::iterator it = views_.find(view_id);
214 if (it != views_.end())
215 views_.erase(it);
216 }
217
218 void ViewTreeClientImpl::OnRootDestroyed(View* root) {
219 DCHECK_EQ(root, root_);
220 root_ = nullptr;
221
222 // When the root is gone we can't do anything useful.
223 if (!in_destructor_)
224 delete this;
225 }
226
227 ////////////////////////////////////////////////////////////////////////////////
228 // ViewTreeClientImpl, ViewTreeConnection implementation:
229
230 Id ViewTreeClientImpl::CreateViewOnServer() {
231 DCHECK(tree_);
232 const Id view_id = MakeTransportId(connection_id_, ++next_id_);
233 tree_->CreateView(view_id, [this](ErrorCode code) {
234 OnActionCompleted(code == ERROR_CODE_NONE);
235 });
236 return view_id;
237 }
238
239 View* ViewTreeClientImpl::GetRoot() {
240 return root_;
241 }
242
243 View* ViewTreeClientImpl::GetViewById(Id id) {
244 IdToViewMap::const_iterator it = views_.find(id);
245 return it != views_.end() ? it->second : NULL;
246 }
247
248 View* ViewTreeClientImpl::GetFocusedView() {
249 return focused_view_;
250 }
251
252 View* ViewTreeClientImpl::CreateView() {
253 View* view = new View(this, CreateViewOnServer());
254 AddView(view);
255 return view;
256 }
257
258 bool ViewTreeClientImpl::IsEmbedRoot() {
259 return is_embed_root_;
260 }
261
262 ConnectionSpecificId ViewTreeClientImpl::GetConnectionId() {
263 return connection_id_;
264 }
265
266 ////////////////////////////////////////////////////////////////////////////////
267 // ViewTreeClientImpl, ViewTreeClient implementation:
268
269 void ViewTreeClientImpl::OnEmbed(ConnectionSpecificId connection_id,
270 ViewDataPtr root_data,
271 ViewTreePtr tree,
272 Id focused_view_id,
273 uint32 access_policy) {
274 if (tree) {
275 DCHECK(!tree_);
276 tree_ = tree.Pass();
277 tree_.set_connection_error_handler([this]() { delete this; });
278 }
279 connection_id_ = connection_id;
280 is_embed_root_ =
281 (access_policy & mojo::ViewTree::ACCESS_POLICY_EMBED_ROOT) != 0;
282
283 DCHECK(!root_);
284 root_ = AddViewToConnection(this, nullptr, root_data);
285
286 focused_view_ = GetViewById(focused_view_id);
287
288 delegate_->OnEmbed(root_);
289 }
290
291 void ViewTreeClientImpl::OnEmbeddedAppDisconnected(Id view_id) {
292 View* view = GetViewById(view_id);
293 if (view) {
294 FOR_EACH_OBSERVER(ViewObserver, *ViewPrivate(view).observers(),
295 OnViewEmbeddedAppDisconnected(view));
296 }
297 }
298
299 void ViewTreeClientImpl::OnUnembed() {
300 delegate_->OnUnembed();
301 // This will send out the various notifications.
302 delete this;
303 }
304
305 void ViewTreeClientImpl::OnViewBoundsChanged(Id view_id,
306 RectPtr old_bounds,
307 RectPtr new_bounds) {
308 View* view = GetViewById(view_id);
309 ViewPrivate(view).LocalSetBounds(*old_bounds, *new_bounds);
310 }
311
312 namespace {
313
314 void SetViewportMetricsOnDecendants(View* root,
315 const ViewportMetrics& old_metrics,
316 const ViewportMetrics& new_metrics) {
317 ViewPrivate(root).LocalSetViewportMetrics(old_metrics, new_metrics);
318 const View::Children& children = root->children();
319 for (size_t i = 0; i < children.size(); ++i)
320 SetViewportMetricsOnDecendants(children[i], old_metrics, new_metrics);
321 }
322 }
323
324 void ViewTreeClientImpl::OnViewViewportMetricsChanged(
325 ViewportMetricsPtr old_metrics,
326 ViewportMetricsPtr new_metrics) {
327 View* view = GetRoot();
328 if (view)
329 SetViewportMetricsOnDecendants(view, *old_metrics, *new_metrics);
330 }
331
332 void ViewTreeClientImpl::OnViewHierarchyChanged(
333 Id view_id,
334 Id new_parent_id,
335 Id old_parent_id,
336 mojo::Array<ViewDataPtr> views) {
337 View* initial_parent = views.size() ?
338 GetViewById(views[0]->parent_id) : NULL;
339
340 const bool was_view_known = GetViewById(view_id) != nullptr;
341
342 BuildViewTree(this, views, initial_parent);
343
344 // If the view was not known, then BuildViewTree() will have created it and
345 // parented the view.
346 if (!was_view_known)
347 return;
348
349 View* new_parent = GetViewById(new_parent_id);
350 View* old_parent = GetViewById(old_parent_id);
351 View* view = GetViewById(view_id);
352 if (new_parent)
353 ViewPrivate(new_parent).LocalAddChild(view);
354 else
355 ViewPrivate(old_parent).LocalRemoveChild(view);
356 }
357
358 void ViewTreeClientImpl::OnViewReordered(Id view_id,
359 Id relative_view_id,
360 OrderDirection direction) {
361 View* view = GetViewById(view_id);
362 View* relative_view = GetViewById(relative_view_id);
363 if (view && relative_view)
364 ViewPrivate(view).LocalReorder(relative_view, direction);
365 }
366
367 void ViewTreeClientImpl::OnViewDeleted(Id view_id) {
368 View* view = GetViewById(view_id);
369 if (view)
370 ViewPrivate(view).LocalDestroy();
371 }
372
373 void ViewTreeClientImpl::OnViewVisibilityChanged(Id view_id, bool visible) {
374 // TODO(sky): there is a race condition here. If this client and another
375 // client change the visibility at the same time the wrong value may be set.
376 // Deal with this some how.
377 View* view = GetViewById(view_id);
378 if (view)
379 ViewPrivate(view).LocalSetVisible(visible);
380 }
381
382 void ViewTreeClientImpl::OnViewDrawnStateChanged(Id view_id, bool drawn) {
383 View* view = GetViewById(view_id);
384 if (view)
385 ViewPrivate(view).LocalSetDrawn(drawn);
386 }
387
388 void ViewTreeClientImpl::OnViewSharedPropertyChanged(
389 Id view_id,
390 const String& name,
391 Array<uint8_t> new_data) {
392 View* view = GetViewById(view_id);
393 if (view) {
394 std::vector<uint8_t> data;
395 std::vector<uint8_t>* data_ptr = NULL;
396 if (!new_data.is_null()) {
397 data = new_data.To<std::vector<uint8_t>>();
398 data_ptr = &data;
399 }
400
401 view->SetSharedProperty(name, data_ptr);
402 }
403 }
404
405 void ViewTreeClientImpl::OnViewInputEvent(
406 Id view_id,
407 EventPtr event,
408 const Callback<void()>& ack_callback) {
409 View* view = GetViewById(view_id);
410 if (view) {
411 FOR_EACH_OBSERVER(ViewObserver,
412 *ViewPrivate(view).observers(),
413 OnViewInputEvent(view, event));
414 }
415 ack_callback.Run();
416 }
417
418 void ViewTreeClientImpl::OnViewFocused(Id focused_view_id) {
419 View* focused = GetViewById(focused_view_id);
420 View* blurred = focused_view_;
421 // Update |focused_view_| before calling any of the observers, so that the
422 // observers get the correct result from calling |View::HasFocus()|,
423 // |ViewTreeConnection::GetFocusedView()| etc.
424 focused_view_ = focused;
425 if (blurred) {
426 FOR_EACH_OBSERVER(ViewObserver, *ViewPrivate(blurred).observers(),
427 OnViewFocusChanged(focused, blurred));
428 }
429 if (focused) {
430 FOR_EACH_OBSERVER(ViewObserver, *ViewPrivate(focused).observers(),
431 OnViewFocusChanged(focused, blurred));
432 }
433 }
434
435 ////////////////////////////////////////////////////////////////////////////////
436 // ViewTreeClientImpl, private:
437
438 void ViewTreeClientImpl::OnActionCompleted(bool success) {
439 if (!change_acked_callback_.is_null())
440 change_acked_callback_.Run();
441 }
442
443 Callback<void(bool)> ViewTreeClientImpl::ActionCompletedCallback() {
444 return [this](bool success) { OnActionCompleted(success); };
445 }
446
447 } // namespace mojo
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698