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

Side by Side Diff: mojo/services/view_manager/connection_manager.cc

Issue 1049993002: Get mojo_shell building inside chromium checkout. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: fix presubmit Created 5 years, 8 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 "mojo/services/view_manager/connection_manager.h"
6
7 #include "base/logging.h"
8 #include "base/stl_util.h"
9 #include "mojo/converters/geometry/geometry_type_converters.h"
10 #include "mojo/converters/input_events/input_events_type_converters.h"
11 #include "mojo/public/interfaces/application/service_provider.mojom.h"
12 #include "mojo/services/view_manager/client_connection.h"
13 #include "mojo/services/view_manager/connection_manager_delegate.h"
14 #include "mojo/services/view_manager/display_manager.h"
15 #include "mojo/services/view_manager/server_view.h"
16 #include "mojo/services/view_manager/view_coordinate_conversions.h"
17 #include "mojo/services/view_manager/view_manager_service_impl.h"
18
19 using mojo::ConnectionSpecificId;
20
21 namespace view_manager {
22 namespace {
23
24 // Creates a copy of |view|. The copied view has |delegate| as its delegate.
25 // This does not recurse.
26 ServerView* CloneView(const ServerView* view, ServerViewDelegate* delegate) {
27 ServerView* clone = new ServerView(delegate, ClonedViewId());
28 clone->SetBounds(view->bounds());
29 clone->SetSurfaceId(view->surface_id());
30 clone->SetOpacity(view->opacity());
31 return clone;
32 }
33
34 // Creates copies of all the visible children of |parent|. Newly cloned views
35 // are added to |cloned_parent| and have |delegate| as their delegate. The
36 // stacking order of the cloned views is preseved.
37 void CloneViewTree(const ServerView* parent,
38 ServerView* cloned_parent,
39 ServerViewDelegate* delegate) {
40 DCHECK(parent->visible());
41 for (const ServerView* to_clone : parent->GetChildren()) {
42 if (to_clone->visible()) {
43 ServerView* cloned = CloneView(to_clone, delegate);
44 cloned_parent->Add(cloned);
45 CloneViewTree(to_clone, cloned, delegate);
46 }
47 }
48 }
49
50 // Recurses through all the children of |view| moving any cloned views to
51 // |new_parent| stacked above |stack_above|. |stack_above| is updated as views
52 // are moved.
53 void ReparentClonedViews(ServerView* new_parent,
54 ServerView** stack_above,
55 ServerView* view) {
56 if (view->id() == ClonedViewId()) {
57 const gfx::Rect new_bounds(ConvertRectBetweenViews(
58 view, new_parent, gfx::Rect(view->bounds().size())));
59 new_parent->Add(view);
60 new_parent->Reorder(view, *stack_above, mojo::ORDER_DIRECTION_ABOVE);
61 view->SetBounds(new_bounds);
62 *stack_above = view;
63 return;
64 }
65
66 for (ServerView* child : view->GetChildren())
67 ReparentClonedViews(new_parent, stack_above, child);
68 }
69
70 // Deletes |view| and all its descendants.
71 void DeleteViewTree(ServerView* view) {
72 for (ServerView* child : view->GetChildren())
73 DeleteViewTree(child);
74
75 delete view;
76 }
77
78 // TODO(sky): nuke, proof of concept.
79 bool DecrementAnimatingViewsOpacity(ServerView* view) {
80 if (view->id() == ClonedViewId()) {
81 const float new_opacity = view->opacity() - .05f;
82 if (new_opacity <= 0)
83 DeleteViewTree(view);
84 else
85 view->SetOpacity(new_opacity);
86 return true;
87 }
88 bool ret_value = false;
89 for (ServerView* child : view->GetChildren()) {
90 if (DecrementAnimatingViewsOpacity(child))
91 ret_value = true;
92 }
93 return ret_value;
94 }
95
96 } // namespace
97
98 ConnectionManager::ScopedChange::ScopedChange(
99 ViewManagerServiceImpl* connection,
100 ConnectionManager* connection_manager,
101 bool is_delete_view)
102 : connection_manager_(connection_manager),
103 connection_id_(connection->id()),
104 is_delete_view_(is_delete_view) {
105 connection_manager_->PrepareForChange(this);
106 }
107
108 ConnectionManager::ScopedChange::~ScopedChange() {
109 connection_manager_->FinishChange();
110 }
111
112 ConnectionManager::ConnectionManager(ConnectionManagerDelegate* delegate,
113 scoped_ptr<DisplayManager> display_manager,
114 mojo::WindowManagerInternal* wm_internal)
115 : delegate_(delegate),
116 window_manager_client_connection_(nullptr),
117 next_connection_id_(1),
118 display_manager_(display_manager.Pass()),
119 root_(new ServerView(this, RootViewId())),
120 wm_internal_(wm_internal),
121 current_change_(nullptr),
122 in_destructor_(false),
123 animation_runner_(base::TimeTicks::Now()) {
124 root_->SetBounds(gfx::Rect(800, 600));
125 root_->SetVisible(true);
126 display_manager_->Init(this);
127 }
128
129 ConnectionManager::~ConnectionManager() {
130 in_destructor_ = true;
131
132 STLDeleteValues(&connection_map_);
133 // All the connections should have been destroyed.
134 DCHECK(connection_map_.empty());
135 root_.reset();
136 }
137
138 ConnectionSpecificId ConnectionManager::GetAndAdvanceNextConnectionId() {
139 const ConnectionSpecificId id = next_connection_id_++;
140 DCHECK_LT(id, next_connection_id_);
141 return id;
142 }
143
144 void ConnectionManager::OnConnectionError(ClientConnection* connection) {
145 if (connection == window_manager_client_connection_) {
146 window_manager_client_connection_ = nullptr;
147 delegate_->OnLostConnectionToWindowManager();
148 // Assume we've been destroyed.
149 return;
150 }
151
152 scoped_ptr<ClientConnection> connection_owner(connection);
153
154 connection_map_.erase(connection->service()->id());
155
156 // Notify remaining connections so that they can cleanup.
157 for (auto& pair : connection_map_) {
158 pair.second->service()->OnWillDestroyViewManagerServiceImpl(
159 connection->service());
160 }
161 }
162
163 void ConnectionManager::EmbedAtView(
164 ConnectionSpecificId creator_id,
165 const std::string& url,
166 const ViewId& view_id,
167 mojo::InterfaceRequest<mojo::ServiceProvider> services,
168 mojo::ServiceProviderPtr exposed_services) {
169 std::string creator_url;
170 ConnectionMap::const_iterator it = connection_map_.find(creator_id);
171 if (it != connection_map_.end())
172 creator_url = it->second->service()->url();
173
174 mojo::ViewManagerServicePtr service_ptr;
175 ClientConnection* client_connection =
176 delegate_->CreateClientConnectionForEmbedAtView(
177 this, GetProxy(&service_ptr), creator_id, creator_url, url, view_id);
178 AddConnection(client_connection);
179 client_connection->service()->Init(client_connection->client(),
180 service_ptr.Pass(), services.Pass(),
181 exposed_services.Pass());
182 OnConnectionMessagedClient(client_connection->service()->id());
183 }
184
185 void ConnectionManager::EmbedAtView(mojo::ConnectionSpecificId creator_id,
186 const ViewId& view_id,
187 mojo::ViewManagerClientPtr client) {
188 std::string creator_url;
189 ConnectionMap::const_iterator it = connection_map_.find(creator_id);
190 if (it != connection_map_.end())
191 creator_url = it->second->service()->url();
192
193 mojo::ViewManagerServicePtr service_ptr;
194 ClientConnection* client_connection =
195 delegate_->CreateClientConnectionForEmbedAtView(
196 this, GetProxy(&service_ptr), creator_id, creator_url, view_id,
197 client.Pass());
198 AddConnection(client_connection);
199 client_connection->service()->Init(client_connection->client(),
200 service_ptr.Pass(), nullptr, nullptr);
201 OnConnectionMessagedClient(client_connection->service()->id());
202 }
203
204 ViewManagerServiceImpl* ConnectionManager::GetConnection(
205 ConnectionSpecificId connection_id) {
206 ConnectionMap::iterator i = connection_map_.find(connection_id);
207 return i == connection_map_.end() ? nullptr : i->second->service();
208 }
209
210 ServerView* ConnectionManager::GetView(const ViewId& id) {
211 if (id == root_->id())
212 return root_.get();
213 ViewManagerServiceImpl* service = GetConnection(id.connection_id);
214 return service ? service->GetView(id) : nullptr;
215 }
216
217 void ConnectionManager::OnConnectionMessagedClient(ConnectionSpecificId id) {
218 if (current_change_)
219 current_change_->MarkConnectionAsMessaged(id);
220 }
221
222 bool ConnectionManager::DidConnectionMessageClient(
223 ConnectionSpecificId id) const {
224 return current_change_ && current_change_->DidMessageConnection(id);
225 }
226
227 const ViewManagerServiceImpl* ConnectionManager::GetConnectionWithRoot(
228 const ViewId& id) const {
229 for (auto& pair : connection_map_) {
230 if (pair.second->service()->IsRoot(id))
231 return pair.second->service();
232 }
233 return nullptr;
234 }
235
236 void ConnectionManager::SetWindowManagerClientConnection(
237 scoped_ptr<ClientConnection> connection) {
238 CHECK(!window_manager_client_connection_);
239 window_manager_client_connection_ = connection.release();
240 AddConnection(window_manager_client_connection_);
241 window_manager_client_connection_->service()->Init(
242 window_manager_client_connection_->client(), nullptr, nullptr, nullptr);
243 }
244
245 mojo::ViewManagerClient*
246 ConnectionManager::GetWindowManagerViewManagerClient() {
247 CHECK(window_manager_client_connection_);
248 return window_manager_client_connection_->client();
249 }
250
251 bool ConnectionManager::CloneAndAnimate(const ViewId& view_id) {
252 ServerView* view = GetView(view_id);
253 if (!view || !view->IsDrawn(root_.get()) || view == root_.get())
254 return false;
255 if (!animation_timer_.IsRunning()) {
256 animation_timer_.Start(FROM_HERE, base::TimeDelta::FromMilliseconds(100),
257 this, &ConnectionManager::DoAnimation);
258 }
259 ServerView* clone = CloneView(view, this);
260 CloneViewTree(view, clone, this);
261 view->parent()->Add(clone);
262 view->parent()->Reorder(clone, view, mojo::ORDER_DIRECTION_ABOVE);
263 return true;
264 }
265
266 void ConnectionManager::ProcessViewBoundsChanged(const ServerView* view,
267 const gfx::Rect& old_bounds,
268 const gfx::Rect& new_bounds) {
269 for (auto& pair : connection_map_) {
270 pair.second->service()->ProcessViewBoundsChanged(
271 view, old_bounds, new_bounds, IsChangeSource(pair.first));
272 }
273 }
274
275 void ConnectionManager::ProcessViewportMetricsChanged(
276 const mojo::ViewportMetrics& old_metrics,
277 const mojo::ViewportMetrics& new_metrics) {
278 for (auto& pair : connection_map_) {
279 pair.second->service()->ProcessViewportMetricsChanged(
280 old_metrics, new_metrics, IsChangeSource(pair.first));
281 }
282 }
283
284 void ConnectionManager::ProcessWillChangeViewHierarchy(
285 const ServerView* view,
286 const ServerView* new_parent,
287 const ServerView* old_parent) {
288 for (auto& pair : connection_map_) {
289 pair.second->service()->ProcessWillChangeViewHierarchy(
290 view, new_parent, old_parent, IsChangeSource(pair.first));
291 }
292 }
293
294 void ConnectionManager::ProcessViewHierarchyChanged(
295 const ServerView* view,
296 const ServerView* new_parent,
297 const ServerView* old_parent) {
298 for (auto& pair : connection_map_) {
299 pair.second->service()->ProcessViewHierarchyChanged(
300 view, new_parent, old_parent, IsChangeSource(pair.first));
301 }
302 }
303
304 void ConnectionManager::ProcessViewReorder(
305 const ServerView* view,
306 const ServerView* relative_view,
307 const mojo::OrderDirection direction) {
308 for (auto& pair : connection_map_) {
309 pair.second->service()->ProcessViewReorder(view, relative_view, direction,
310 IsChangeSource(pair.first));
311 }
312 }
313
314 void ConnectionManager::ProcessViewDeleted(const ViewId& view) {
315 for (auto& pair : connection_map_) {
316 pair.second->service()->ProcessViewDeleted(view,
317 IsChangeSource(pair.first));
318 }
319 }
320
321 void ConnectionManager::PrepareForChange(ScopedChange* change) {
322 // Should only ever have one change in flight.
323 CHECK(!current_change_);
324 current_change_ = change;
325 }
326
327 void ConnectionManager::FinishChange() {
328 // PrepareForChange/FinishChange should be balanced.
329 CHECK(current_change_);
330 current_change_ = NULL;
331 }
332
333 void ConnectionManager::DoAnimation() {
334 if (!DecrementAnimatingViewsOpacity(root()))
335 animation_timer_.Stop();
336 }
337
338 void ConnectionManager::AddConnection(ClientConnection* connection) {
339 DCHECK_EQ(0u, connection_map_.count(connection->service()->id()));
340 connection_map_[connection->service()->id()] = connection;
341 }
342
343 void ConnectionManager::OnWillDestroyView(ServerView* view) {
344 if (!in_destructor_ && root_->Contains(view) && view != root_.get() &&
345 view->id() != ClonedViewId()) {
346 // We're about to destroy a view. Any cloned views need to be reparented
347 // else the animation would no longer be visible. By moving to a visible
348 // view, view->parent(), we ensure the animation is still visible.
349 ServerView* parent_above = view;
350 ReparentClonedViews(view->parent(), &parent_above, view);
351 }
352
353 animation_runner_.CancelAnimationForView(view);
354 }
355
356 void ConnectionManager::OnViewDestroyed(const ServerView* view) {
357 if (!in_destructor_)
358 ProcessViewDeleted(view->id());
359 }
360
361 void ConnectionManager::OnWillChangeViewHierarchy(ServerView* view,
362 ServerView* new_parent,
363 ServerView* old_parent) {
364 if (view->id() == ClonedViewId() || in_destructor_)
365 return;
366
367 if (root_->Contains(view) && view != root_.get()) {
368 // We're about to reparent a view. Any cloned views need to be reparented
369 // else the animation may be effected in unusual ways. For example, the view
370 // could move to a new location such that the animation is entirely clipped.
371 // By moving to view->parent() we ensure the animation is still visible.
372 ServerView* parent_above = view;
373 ReparentClonedViews(view->parent(), &parent_above, view);
374 }
375
376 ProcessWillChangeViewHierarchy(view, new_parent, old_parent);
377
378 animation_runner_.CancelAnimationForView(view);
379 }
380
381 void ConnectionManager::OnViewHierarchyChanged(const ServerView* view,
382 const ServerView* new_parent,
383 const ServerView* old_parent) {
384 if (in_destructor_)
385 return;
386
387 ProcessViewHierarchyChanged(view, new_parent, old_parent);
388
389 // TODO(beng): optimize.
390 if (old_parent) {
391 display_manager_->SchedulePaint(old_parent,
392 gfx::Rect(old_parent->bounds().size()));
393 }
394 if (new_parent) {
395 display_manager_->SchedulePaint(new_parent,
396 gfx::Rect(new_parent->bounds().size()));
397 }
398 }
399
400 void ConnectionManager::OnViewBoundsChanged(const ServerView* view,
401 const gfx::Rect& old_bounds,
402 const gfx::Rect& new_bounds) {
403 if (in_destructor_)
404 return;
405
406 ProcessViewBoundsChanged(view, old_bounds, new_bounds);
407 if (!view->parent())
408 return;
409
410 // TODO(sky): optimize this.
411 display_manager_->SchedulePaint(view->parent(), old_bounds);
412 display_manager_->SchedulePaint(view->parent(), new_bounds);
413 }
414
415 void ConnectionManager::OnViewSurfaceIdChanged(const ServerView* view) {
416 if (!in_destructor_)
417 display_manager_->SchedulePaint(view, gfx::Rect(view->bounds().size()));
418 }
419
420 void ConnectionManager::OnViewReordered(const ServerView* view,
421 const ServerView* relative,
422 mojo::OrderDirection direction) {
423 if (!in_destructor_)
424 display_manager_->SchedulePaint(view, gfx::Rect(view->bounds().size()));
425 }
426
427 void ConnectionManager::OnWillChangeViewVisibility(ServerView* view) {
428 if (in_destructor_)
429 return;
430
431 // Need to repaint if the view was drawn (which means it'll in the process of
432 // hiding) or the view is transitioning to drawn.
433 if (view->IsDrawn(root_.get()) || (!view->visible() && view->parent() &&
434 view->parent()->IsDrawn(root_.get()))) {
435 display_manager_->SchedulePaint(view->parent(), view->bounds());
436 }
437
438 if (view != root_.get() && view->id() != ClonedViewId() &&
439 root_->Contains(view) && view->IsDrawn(root_.get())) {
440 // We're about to hide |view|, this would implicitly make any cloned views
441 // hide to. Reparent so that animations are still visible.
442 ServerView* parent_above = view;
443 ReparentClonedViews(view->parent(), &parent_above, view);
444 }
445
446 for (auto& pair : connection_map_) {
447 pair.second->service()->ProcessWillChangeViewVisibility(
448 view, IsChangeSource(pair.first));
449 }
450
451 const bool is_parent_drawn =
452 view->parent() && view->parent()->IsDrawn(root_.get());
453 if (!is_parent_drawn || !view->visible())
454 animation_runner_.CancelAnimationForView(view);
455 }
456
457 void ConnectionManager::OnViewSharedPropertyChanged(
458 const ServerView* view,
459 const std::string& name,
460 const std::vector<uint8_t>* new_data) {
461 for (auto& pair : connection_map_) {
462 pair.second->service()->ProcessViewPropertyChanged(
463 view, name, new_data, IsChangeSource(pair.first));
464 }
465 }
466
467 void ConnectionManager::OnScheduleViewPaint(const ServerView* view) {
468 if (!in_destructor_)
469 display_manager_->SchedulePaint(view, gfx::Rect(view->bounds().size()));
470 }
471
472 void ConnectionManager::DispatchInputEventToView(mojo::Id transport_view_id,
473 mojo::EventPtr event) {
474 const ViewId view_id(ViewIdFromTransportId(transport_view_id));
475
476 ViewManagerServiceImpl* connection = GetConnectionWithRoot(view_id);
477 if (!connection)
478 connection = GetConnection(view_id.connection_id);
479 if (connection) {
480 connection->client()->OnViewInputEvent(
481 transport_view_id, event.Pass(), base::Bind(&base::DoNothing));
482 }
483 }
484
485 void ConnectionManager::SetViewportSize(mojo::SizePtr size) {
486 gfx::Size new_size = size.To<gfx::Size>();
487 display_manager_->SetViewportSize(new_size);
488 }
489
490 void ConnectionManager::CloneAndAnimate(mojo::Id transport_view_id) {
491 CloneAndAnimate(ViewIdFromTransportId(transport_view_id));
492 }
493
494 } // namespace view_manager
OLDNEW
« no previous file with comments | « mojo/services/view_manager/connection_manager.h ('k') | mojo/services/view_manager/connection_manager_delegate.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698