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

Unified 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, 9 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 side-by-side diff with in-line comments
Download patch
Index: mojo/services/view_manager/connection_manager.cc
diff --git a/mojo/services/view_manager/connection_manager.cc b/mojo/services/view_manager/connection_manager.cc
new file mode 100644
index 0000000000000000000000000000000000000000..768d0ff2f6fba9e255468b2f0742f9722da0cba5
--- /dev/null
+++ b/mojo/services/view_manager/connection_manager.cc
@@ -0,0 +1,494 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "mojo/services/view_manager/connection_manager.h"
+
+#include "base/logging.h"
+#include "base/stl_util.h"
+#include "mojo/converters/geometry/geometry_type_converters.h"
+#include "mojo/converters/input_events/input_events_type_converters.h"
+#include "mojo/public/interfaces/application/service_provider.mojom.h"
+#include "mojo/services/view_manager/client_connection.h"
+#include "mojo/services/view_manager/connection_manager_delegate.h"
+#include "mojo/services/view_manager/display_manager.h"
+#include "mojo/services/view_manager/server_view.h"
+#include "mojo/services/view_manager/view_coordinate_conversions.h"
+#include "mojo/services/view_manager/view_manager_service_impl.h"
+
+using mojo::ConnectionSpecificId;
+
+namespace view_manager {
+namespace {
+
+// Creates a copy of |view|. The copied view has |delegate| as its delegate.
+// This does not recurse.
+ServerView* CloneView(const ServerView* view, ServerViewDelegate* delegate) {
+ ServerView* clone = new ServerView(delegate, ClonedViewId());
+ clone->SetBounds(view->bounds());
+ clone->SetSurfaceId(view->surface_id());
+ clone->SetOpacity(view->opacity());
+ return clone;
+}
+
+// Creates copies of all the visible children of |parent|. Newly cloned views
+// are added to |cloned_parent| and have |delegate| as their delegate. The
+// stacking order of the cloned views is preseved.
+void CloneViewTree(const ServerView* parent,
+ ServerView* cloned_parent,
+ ServerViewDelegate* delegate) {
+ DCHECK(parent->visible());
+ for (const ServerView* to_clone : parent->GetChildren()) {
+ if (to_clone->visible()) {
+ ServerView* cloned = CloneView(to_clone, delegate);
+ cloned_parent->Add(cloned);
+ CloneViewTree(to_clone, cloned, delegate);
+ }
+ }
+}
+
+// Recurses through all the children of |view| moving any cloned views to
+// |new_parent| stacked above |stack_above|. |stack_above| is updated as views
+// are moved.
+void ReparentClonedViews(ServerView* new_parent,
+ ServerView** stack_above,
+ ServerView* view) {
+ if (view->id() == ClonedViewId()) {
+ const gfx::Rect new_bounds(ConvertRectBetweenViews(
+ view, new_parent, gfx::Rect(view->bounds().size())));
+ new_parent->Add(view);
+ new_parent->Reorder(view, *stack_above, mojo::ORDER_DIRECTION_ABOVE);
+ view->SetBounds(new_bounds);
+ *stack_above = view;
+ return;
+ }
+
+ for (ServerView* child : view->GetChildren())
+ ReparentClonedViews(new_parent, stack_above, child);
+}
+
+// Deletes |view| and all its descendants.
+void DeleteViewTree(ServerView* view) {
+ for (ServerView* child : view->GetChildren())
+ DeleteViewTree(child);
+
+ delete view;
+}
+
+// TODO(sky): nuke, proof of concept.
+bool DecrementAnimatingViewsOpacity(ServerView* view) {
+ if (view->id() == ClonedViewId()) {
+ const float new_opacity = view->opacity() - .05f;
+ if (new_opacity <= 0)
+ DeleteViewTree(view);
+ else
+ view->SetOpacity(new_opacity);
+ return true;
+ }
+ bool ret_value = false;
+ for (ServerView* child : view->GetChildren()) {
+ if (DecrementAnimatingViewsOpacity(child))
+ ret_value = true;
+ }
+ return ret_value;
+}
+
+} // namespace
+
+ConnectionManager::ScopedChange::ScopedChange(
+ ViewManagerServiceImpl* connection,
+ ConnectionManager* connection_manager,
+ bool is_delete_view)
+ : connection_manager_(connection_manager),
+ connection_id_(connection->id()),
+ is_delete_view_(is_delete_view) {
+ connection_manager_->PrepareForChange(this);
+}
+
+ConnectionManager::ScopedChange::~ScopedChange() {
+ connection_manager_->FinishChange();
+}
+
+ConnectionManager::ConnectionManager(ConnectionManagerDelegate* delegate,
+ scoped_ptr<DisplayManager> display_manager,
+ mojo::WindowManagerInternal* wm_internal)
+ : delegate_(delegate),
+ window_manager_client_connection_(nullptr),
+ next_connection_id_(1),
+ display_manager_(display_manager.Pass()),
+ root_(new ServerView(this, RootViewId())),
+ wm_internal_(wm_internal),
+ current_change_(nullptr),
+ in_destructor_(false),
+ animation_runner_(base::TimeTicks::Now()) {
+ root_->SetBounds(gfx::Rect(800, 600));
+ root_->SetVisible(true);
+ display_manager_->Init(this);
+}
+
+ConnectionManager::~ConnectionManager() {
+ in_destructor_ = true;
+
+ STLDeleteValues(&connection_map_);
+ // All the connections should have been destroyed.
+ DCHECK(connection_map_.empty());
+ root_.reset();
+}
+
+ConnectionSpecificId ConnectionManager::GetAndAdvanceNextConnectionId() {
+ const ConnectionSpecificId id = next_connection_id_++;
+ DCHECK_LT(id, next_connection_id_);
+ return id;
+}
+
+void ConnectionManager::OnConnectionError(ClientConnection* connection) {
+ if (connection == window_manager_client_connection_) {
+ window_manager_client_connection_ = nullptr;
+ delegate_->OnLostConnectionToWindowManager();
+ // Assume we've been destroyed.
+ return;
+ }
+
+ scoped_ptr<ClientConnection> connection_owner(connection);
+
+ connection_map_.erase(connection->service()->id());
+
+ // Notify remaining connections so that they can cleanup.
+ for (auto& pair : connection_map_) {
+ pair.second->service()->OnWillDestroyViewManagerServiceImpl(
+ connection->service());
+ }
+}
+
+void ConnectionManager::EmbedAtView(
+ ConnectionSpecificId creator_id,
+ const std::string& url,
+ const ViewId& view_id,
+ mojo::InterfaceRequest<mojo::ServiceProvider> services,
+ mojo::ServiceProviderPtr exposed_services) {
+ std::string creator_url;
+ ConnectionMap::const_iterator it = connection_map_.find(creator_id);
+ if (it != connection_map_.end())
+ creator_url = it->second->service()->url();
+
+ mojo::ViewManagerServicePtr service_ptr;
+ ClientConnection* client_connection =
+ delegate_->CreateClientConnectionForEmbedAtView(
+ this, GetProxy(&service_ptr), creator_id, creator_url, url, view_id);
+ AddConnection(client_connection);
+ client_connection->service()->Init(client_connection->client(),
+ service_ptr.Pass(), services.Pass(),
+ exposed_services.Pass());
+ OnConnectionMessagedClient(client_connection->service()->id());
+}
+
+void ConnectionManager::EmbedAtView(mojo::ConnectionSpecificId creator_id,
+ const ViewId& view_id,
+ mojo::ViewManagerClientPtr client) {
+ std::string creator_url;
+ ConnectionMap::const_iterator it = connection_map_.find(creator_id);
+ if (it != connection_map_.end())
+ creator_url = it->second->service()->url();
+
+ mojo::ViewManagerServicePtr service_ptr;
+ ClientConnection* client_connection =
+ delegate_->CreateClientConnectionForEmbedAtView(
+ this, GetProxy(&service_ptr), creator_id, creator_url, view_id,
+ client.Pass());
+ AddConnection(client_connection);
+ client_connection->service()->Init(client_connection->client(),
+ service_ptr.Pass(), nullptr, nullptr);
+ OnConnectionMessagedClient(client_connection->service()->id());
+}
+
+ViewManagerServiceImpl* ConnectionManager::GetConnection(
+ ConnectionSpecificId connection_id) {
+ ConnectionMap::iterator i = connection_map_.find(connection_id);
+ return i == connection_map_.end() ? nullptr : i->second->service();
+}
+
+ServerView* ConnectionManager::GetView(const ViewId& id) {
+ if (id == root_->id())
+ return root_.get();
+ ViewManagerServiceImpl* service = GetConnection(id.connection_id);
+ return service ? service->GetView(id) : nullptr;
+}
+
+void ConnectionManager::OnConnectionMessagedClient(ConnectionSpecificId id) {
+ if (current_change_)
+ current_change_->MarkConnectionAsMessaged(id);
+}
+
+bool ConnectionManager::DidConnectionMessageClient(
+ ConnectionSpecificId id) const {
+ return current_change_ && current_change_->DidMessageConnection(id);
+}
+
+const ViewManagerServiceImpl* ConnectionManager::GetConnectionWithRoot(
+ const ViewId& id) const {
+ for (auto& pair : connection_map_) {
+ if (pair.second->service()->IsRoot(id))
+ return pair.second->service();
+ }
+ return nullptr;
+}
+
+void ConnectionManager::SetWindowManagerClientConnection(
+ scoped_ptr<ClientConnection> connection) {
+ CHECK(!window_manager_client_connection_);
+ window_manager_client_connection_ = connection.release();
+ AddConnection(window_manager_client_connection_);
+ window_manager_client_connection_->service()->Init(
+ window_manager_client_connection_->client(), nullptr, nullptr, nullptr);
+}
+
+mojo::ViewManagerClient*
+ConnectionManager::GetWindowManagerViewManagerClient() {
+ CHECK(window_manager_client_connection_);
+ return window_manager_client_connection_->client();
+}
+
+bool ConnectionManager::CloneAndAnimate(const ViewId& view_id) {
+ ServerView* view = GetView(view_id);
+ if (!view || !view->IsDrawn(root_.get()) || view == root_.get())
+ return false;
+ if (!animation_timer_.IsRunning()) {
+ animation_timer_.Start(FROM_HERE, base::TimeDelta::FromMilliseconds(100),
+ this, &ConnectionManager::DoAnimation);
+ }
+ ServerView* clone = CloneView(view, this);
+ CloneViewTree(view, clone, this);
+ view->parent()->Add(clone);
+ view->parent()->Reorder(clone, view, mojo::ORDER_DIRECTION_ABOVE);
+ return true;
+}
+
+void ConnectionManager::ProcessViewBoundsChanged(const ServerView* view,
+ const gfx::Rect& old_bounds,
+ const gfx::Rect& new_bounds) {
+ for (auto& pair : connection_map_) {
+ pair.second->service()->ProcessViewBoundsChanged(
+ view, old_bounds, new_bounds, IsChangeSource(pair.first));
+ }
+}
+
+void ConnectionManager::ProcessViewportMetricsChanged(
+ const mojo::ViewportMetrics& old_metrics,
+ const mojo::ViewportMetrics& new_metrics) {
+ for (auto& pair : connection_map_) {
+ pair.second->service()->ProcessViewportMetricsChanged(
+ old_metrics, new_metrics, IsChangeSource(pair.first));
+ }
+}
+
+void ConnectionManager::ProcessWillChangeViewHierarchy(
+ const ServerView* view,
+ const ServerView* new_parent,
+ const ServerView* old_parent) {
+ for (auto& pair : connection_map_) {
+ pair.second->service()->ProcessWillChangeViewHierarchy(
+ view, new_parent, old_parent, IsChangeSource(pair.first));
+ }
+}
+
+void ConnectionManager::ProcessViewHierarchyChanged(
+ const ServerView* view,
+ const ServerView* new_parent,
+ const ServerView* old_parent) {
+ for (auto& pair : connection_map_) {
+ pair.second->service()->ProcessViewHierarchyChanged(
+ view, new_parent, old_parent, IsChangeSource(pair.first));
+ }
+}
+
+void ConnectionManager::ProcessViewReorder(
+ const ServerView* view,
+ const ServerView* relative_view,
+ const mojo::OrderDirection direction) {
+ for (auto& pair : connection_map_) {
+ pair.second->service()->ProcessViewReorder(view, relative_view, direction,
+ IsChangeSource(pair.first));
+ }
+}
+
+void ConnectionManager::ProcessViewDeleted(const ViewId& view) {
+ for (auto& pair : connection_map_) {
+ pair.second->service()->ProcessViewDeleted(view,
+ IsChangeSource(pair.first));
+ }
+}
+
+void ConnectionManager::PrepareForChange(ScopedChange* change) {
+ // Should only ever have one change in flight.
+ CHECK(!current_change_);
+ current_change_ = change;
+}
+
+void ConnectionManager::FinishChange() {
+ // PrepareForChange/FinishChange should be balanced.
+ CHECK(current_change_);
+ current_change_ = NULL;
+}
+
+void ConnectionManager::DoAnimation() {
+ if (!DecrementAnimatingViewsOpacity(root()))
+ animation_timer_.Stop();
+}
+
+void ConnectionManager::AddConnection(ClientConnection* connection) {
+ DCHECK_EQ(0u, connection_map_.count(connection->service()->id()));
+ connection_map_[connection->service()->id()] = connection;
+}
+
+void ConnectionManager::OnWillDestroyView(ServerView* view) {
+ if (!in_destructor_ && root_->Contains(view) && view != root_.get() &&
+ view->id() != ClonedViewId()) {
+ // We're about to destroy a view. Any cloned views need to be reparented
+ // else the animation would no longer be visible. By moving to a visible
+ // view, view->parent(), we ensure the animation is still visible.
+ ServerView* parent_above = view;
+ ReparentClonedViews(view->parent(), &parent_above, view);
+ }
+
+ animation_runner_.CancelAnimationForView(view);
+}
+
+void ConnectionManager::OnViewDestroyed(const ServerView* view) {
+ if (!in_destructor_)
+ ProcessViewDeleted(view->id());
+}
+
+void ConnectionManager::OnWillChangeViewHierarchy(ServerView* view,
+ ServerView* new_parent,
+ ServerView* old_parent) {
+ if (view->id() == ClonedViewId() || in_destructor_)
+ return;
+
+ if (root_->Contains(view) && view != root_.get()) {
+ // We're about to reparent a view. Any cloned views need to be reparented
+ // else the animation may be effected in unusual ways. For example, the view
+ // could move to a new location such that the animation is entirely clipped.
+ // By moving to view->parent() we ensure the animation is still visible.
+ ServerView* parent_above = view;
+ ReparentClonedViews(view->parent(), &parent_above, view);
+ }
+
+ ProcessWillChangeViewHierarchy(view, new_parent, old_parent);
+
+ animation_runner_.CancelAnimationForView(view);
+}
+
+void ConnectionManager::OnViewHierarchyChanged(const ServerView* view,
+ const ServerView* new_parent,
+ const ServerView* old_parent) {
+ if (in_destructor_)
+ return;
+
+ ProcessViewHierarchyChanged(view, new_parent, old_parent);
+
+ // TODO(beng): optimize.
+ if (old_parent) {
+ display_manager_->SchedulePaint(old_parent,
+ gfx::Rect(old_parent->bounds().size()));
+ }
+ if (new_parent) {
+ display_manager_->SchedulePaint(new_parent,
+ gfx::Rect(new_parent->bounds().size()));
+ }
+}
+
+void ConnectionManager::OnViewBoundsChanged(const ServerView* view,
+ const gfx::Rect& old_bounds,
+ const gfx::Rect& new_bounds) {
+ if (in_destructor_)
+ return;
+
+ ProcessViewBoundsChanged(view, old_bounds, new_bounds);
+ if (!view->parent())
+ return;
+
+ // TODO(sky): optimize this.
+ display_manager_->SchedulePaint(view->parent(), old_bounds);
+ display_manager_->SchedulePaint(view->parent(), new_bounds);
+}
+
+void ConnectionManager::OnViewSurfaceIdChanged(const ServerView* view) {
+ if (!in_destructor_)
+ display_manager_->SchedulePaint(view, gfx::Rect(view->bounds().size()));
+}
+
+void ConnectionManager::OnViewReordered(const ServerView* view,
+ const ServerView* relative,
+ mojo::OrderDirection direction) {
+ if (!in_destructor_)
+ display_manager_->SchedulePaint(view, gfx::Rect(view->bounds().size()));
+}
+
+void ConnectionManager::OnWillChangeViewVisibility(ServerView* view) {
+ if (in_destructor_)
+ return;
+
+ // Need to repaint if the view was drawn (which means it'll in the process of
+ // hiding) or the view is transitioning to drawn.
+ if (view->IsDrawn(root_.get()) || (!view->visible() && view->parent() &&
+ view->parent()->IsDrawn(root_.get()))) {
+ display_manager_->SchedulePaint(view->parent(), view->bounds());
+ }
+
+ if (view != root_.get() && view->id() != ClonedViewId() &&
+ root_->Contains(view) && view->IsDrawn(root_.get())) {
+ // We're about to hide |view|, this would implicitly make any cloned views
+ // hide to. Reparent so that animations are still visible.
+ ServerView* parent_above = view;
+ ReparentClonedViews(view->parent(), &parent_above, view);
+ }
+
+ for (auto& pair : connection_map_) {
+ pair.second->service()->ProcessWillChangeViewVisibility(
+ view, IsChangeSource(pair.first));
+ }
+
+ const bool is_parent_drawn =
+ view->parent() && view->parent()->IsDrawn(root_.get());
+ if (!is_parent_drawn || !view->visible())
+ animation_runner_.CancelAnimationForView(view);
+}
+
+void ConnectionManager::OnViewSharedPropertyChanged(
+ const ServerView* view,
+ const std::string& name,
+ const std::vector<uint8_t>* new_data) {
+ for (auto& pair : connection_map_) {
+ pair.second->service()->ProcessViewPropertyChanged(
+ view, name, new_data, IsChangeSource(pair.first));
+ }
+}
+
+void ConnectionManager::OnScheduleViewPaint(const ServerView* view) {
+ if (!in_destructor_)
+ display_manager_->SchedulePaint(view, gfx::Rect(view->bounds().size()));
+}
+
+void ConnectionManager::DispatchInputEventToView(mojo::Id transport_view_id,
+ mojo::EventPtr event) {
+ const ViewId view_id(ViewIdFromTransportId(transport_view_id));
+
+ ViewManagerServiceImpl* connection = GetConnectionWithRoot(view_id);
+ if (!connection)
+ connection = GetConnection(view_id.connection_id);
+ if (connection) {
+ connection->client()->OnViewInputEvent(
+ transport_view_id, event.Pass(), base::Bind(&base::DoNothing));
+ }
+}
+
+void ConnectionManager::SetViewportSize(mojo::SizePtr size) {
+ gfx::Size new_size = size.To<gfx::Size>();
+ display_manager_->SetViewportSize(new_size);
+}
+
+void ConnectionManager::CloneAndAnimate(mojo::Id transport_view_id) {
+ CloneAndAnimate(ViewIdFromTransportId(transport_view_id));
+}
+
+} // namespace view_manager
« 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