diff options
Diffstat (limited to 'chromium/mojo/services/view_manager/root_node_manager.cc')
-rw-r--r-- | chromium/mojo/services/view_manager/root_node_manager.cc | 265 |
1 files changed, 265 insertions, 0 deletions
diff --git a/chromium/mojo/services/view_manager/root_node_manager.cc b/chromium/mojo/services/view_manager/root_node_manager.cc new file mode 100644 index 00000000000..f5c681fc7a1 --- /dev/null +++ b/chromium/mojo/services/view_manager/root_node_manager.cc @@ -0,0 +1,265 @@ +// 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/root_node_manager.h" + +#include "base/logging.h" +#include "mojo/public/interfaces/service_provider/service_provider.mojom.h" +#include "mojo/services/public/cpp/input_events/input_events_type_converters.h" +#include "mojo/services/view_manager/view.h" +#include "mojo/services/view_manager/view_manager_service_impl.h" +#include "ui/aura/env.h" + +namespace mojo { +namespace view_manager { +namespace service { + +RootNodeManager::ScopedChange::ScopedChange( + ViewManagerServiceImpl* connection, + RootNodeManager* root, + RootNodeManager::ChangeType change_type, + bool is_delete_node) + : root_(root), + connection_id_(connection->id()), + change_type_(change_type), + is_delete_node_(is_delete_node) { + root_->PrepareForChange(this); +} + +RootNodeManager::ScopedChange::~ScopedChange() { + root_->FinishChange(); +} + +RootNodeManager::Context::Context() { + // Pass in false as native viewport creates the PlatformEventSource. + aura::Env::CreateInstance(false); +} + +RootNodeManager::Context::~Context() { + aura::Env::DeleteInstance(); +} + +RootNodeManager::RootNodeManager(ServiceProvider* service_provider, + RootViewManagerDelegate* view_manager_delegate) + : service_provider_(service_provider), + next_connection_id_(1), + next_server_change_id_(1), + root_view_manager_(service_provider, this, view_manager_delegate), + root_(this, RootNodeId()), + current_change_(NULL) { +} + +RootNodeManager::~RootNodeManager() { + while (!connections_created_by_connect_.empty()) + delete *(connections_created_by_connect_.begin()); + // All the connections should have been destroyed. + DCHECK(connection_map_.empty()); +} + +ConnectionSpecificId RootNodeManager::GetAndAdvanceNextConnectionId() { + const ConnectionSpecificId id = next_connection_id_++; + DCHECK_LT(id, next_connection_id_); + return id; +} + +void RootNodeManager::AddConnection(ViewManagerServiceImpl* connection) { + DCHECK_EQ(0u, connection_map_.count(connection->id())); + connection_map_[connection->id()] = connection; +} + +void RootNodeManager::RemoveConnection(ViewManagerServiceImpl* connection) { + connection_map_.erase(connection->id()); + connections_created_by_connect_.erase(connection); + + // Notify remaining connections so that they can cleanup. + for (ConnectionMap::const_iterator i = connection_map_.begin(); + i != connection_map_.end(); ++i) { + i->second->OnViewManagerServiceImplDestroyed(connection->id()); + } +} + +void RootNodeManager::EmbedRoot(const std::string& url) { + CHECK(connection_map_.empty()); + Array<Id> roots(0); + EmbedImpl(kRootConnection, String::From(url), roots); +} + +void RootNodeManager::Embed(ConnectionSpecificId creator_id, + const String& url, + const Array<Id>& node_ids) { + CHECK_GT(node_ids.size(), 0u); + EmbedImpl(creator_id, url, node_ids)->set_delete_on_connection_error(); +} + +ViewManagerServiceImpl* RootNodeManager::GetConnection( + ConnectionSpecificId connection_id) { + ConnectionMap::iterator i = connection_map_.find(connection_id); + return i == connection_map_.end() ? NULL : i->second; +} + +Node* RootNodeManager::GetNode(const NodeId& id) { + if (id == root_.id()) + return &root_; + ConnectionMap::iterator i = connection_map_.find(id.connection_id); + return i == connection_map_.end() ? NULL : i->second->GetNode(id); +} + +View* RootNodeManager::GetView(const ViewId& id) { + ConnectionMap::iterator i = connection_map_.find(id.connection_id); + return i == connection_map_.end() ? NULL : i->second->GetView(id); +} + +void RootNodeManager::OnConnectionMessagedClient(ConnectionSpecificId id) { + if (current_change_) + current_change_->MarkConnectionAsMessaged(id); +} + +bool RootNodeManager::DidConnectionMessageClient( + ConnectionSpecificId id) const { + return current_change_ && current_change_->DidMessageConnection(id); +} + +ViewManagerServiceImpl* RootNodeManager::GetConnectionByCreator( + ConnectionSpecificId creator_id, + const std::string& url) const { + for (ConnectionMap::const_iterator i = connection_map_.begin(); + i != connection_map_.end(); ++i) { + if (i->second->creator_id() == creator_id && i->second->url() == url) + return i->second; + } + return NULL; +} + +void RootNodeManager::DispatchViewInputEventToWindowManager( + const View* view, + const ui::Event* event) { + // Input events are forwarded to the WindowManager. The WindowManager + // eventually calls back to us with DispatchOnViewInputEvent(). + ViewManagerServiceImpl* connection = GetConnection(kWindowManagerConnection); + if (!connection) + return; + connection->client()->DispatchOnViewInputEvent( + ViewIdToTransportId(view->id()), + TypeConverter<EventPtr, ui::Event>::ConvertFrom(*event)); +} + +void RootNodeManager::ProcessNodeBoundsChanged(const Node* node, + const gfx::Rect& old_bounds, + const gfx::Rect& new_bounds) { + for (ConnectionMap::iterator i = connection_map_.begin(); + i != connection_map_.end(); ++i) { + i->second->ProcessNodeBoundsChanged(node, old_bounds, new_bounds, + IsChangeSource(i->first)); + } +} + +void RootNodeManager::ProcessNodeHierarchyChanged(const Node* node, + const Node* new_parent, + const Node* old_parent) { + for (ConnectionMap::iterator i = connection_map_.begin(); + i != connection_map_.end(); ++i) { + i->second->ProcessNodeHierarchyChanged( + node, new_parent, old_parent, next_server_change_id_, + IsChangeSource(i->first)); + } +} + +void RootNodeManager::ProcessNodeReorder(const Node* node, + const Node* relative_node, + const OrderDirection direction) { + for (ConnectionMap::iterator i = connection_map_.begin(); + i != connection_map_.end(); ++i) { + i->second->ProcessNodeReorder( + node, relative_node, direction, next_server_change_id_, + IsChangeSource(i->first)); + } +} + +void RootNodeManager::ProcessNodeViewReplaced(const Node* node, + const View* new_view, + const View* old_view) { + for (ConnectionMap::iterator i = connection_map_.begin(); + i != connection_map_.end(); ++i) { + i->second->ProcessNodeViewReplaced(node, new_view, old_view, + IsChangeSource(i->first)); + } +} + +void RootNodeManager::ProcessNodeDeleted(const NodeId& node) { + for (ConnectionMap::iterator i = connection_map_.begin(); + i != connection_map_.end(); ++i) { + i->second->ProcessNodeDeleted(node, next_server_change_id_, + IsChangeSource(i->first)); + } +} + +void RootNodeManager::ProcessViewDeleted(const ViewId& view) { + for (ConnectionMap::iterator i = connection_map_.begin(); + i != connection_map_.end(); ++i) { + i->second->ProcessViewDeleted(view, IsChangeSource(i->first)); + } +} + +void RootNodeManager::PrepareForChange(ScopedChange* change) { + // Should only ever have one change in flight. + CHECK(!current_change_); + current_change_ = change; +} + +void RootNodeManager::FinishChange() { + // PrepareForChange/FinishChange should be balanced. + CHECK(current_change_); + if (current_change_->change_type() == CHANGE_TYPE_ADVANCE_SERVER_CHANGE_ID) + next_server_change_id_++; + current_change_ = NULL; +} + +ViewManagerServiceImpl* RootNodeManager::EmbedImpl( + const ConnectionSpecificId creator_id, + const String& url, + const Array<Id>& node_ids) { + MessagePipe pipe; + service_provider_->ConnectToService( + url, + ViewManagerServiceImpl::Client::Name_, + pipe.handle1.Pass(), + String()); + + std::string creator_url; + ConnectionMap::const_iterator it = connection_map_.find(creator_id); + if (it != connection_map_.end()) + creator_url = it->second->url(); + + ViewManagerServiceImpl* connection = + new ViewManagerServiceImpl(this, + creator_id, + creator_url, + url.To<std::string>()); + connection->SetRoots(node_ids); + BindToPipe(connection, pipe.handle0.Pass()); + connections_created_by_connect_.insert(connection); + return connection; +} + +void RootNodeManager::OnNodeHierarchyChanged(const Node* node, + const Node* new_parent, + const Node* old_parent) { + if (!root_view_manager_.in_setup()) + ProcessNodeHierarchyChanged(node, new_parent, old_parent); +} + +void RootNodeManager::OnNodeViewReplaced(const Node* node, + const View* new_view, + const View* old_view) { + ProcessNodeViewReplaced(node, new_view, old_view); +} + +void RootNodeManager::OnViewInputEvent(const View* view, + const ui::Event* event) { + DispatchViewInputEventToWindowManager(view, event); +} + +} // namespace service +} // namespace view_manager +} // namespace mojo |