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

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

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

Powered by Google App Engine
This is Rietveld 408576698