Commit d0e2cfcb authored by ben@chromium.org's avatar ben@chromium.org

Add an example that nests embedded app, so we have two levels of nesting (and...

Add an example that nests embedded app, so we have two levels of nesting (and thus two connections).

I realized an error in understanding of ServiceConnection et al and have corrected this with this CL. ViewManager is now instantiated by the synchronizer. For a given app instance there may be N instances of ViewManager, one per unique connection. Code utilizing ViewManager needs to be more careful about which instance they pass.

R=sky@chromium.org
http://crbug.com/365012

Review URL: https://codereview.chromium.org/311373005

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@275609 0039d316-1c4b-4281-b951-d872f2087c98
parent 3138ad08
......@@ -8,6 +8,7 @@
#include "mojo/public/cpp/application/application.h"
#include "mojo/services/public/cpp/view_manager/view.h"
#include "mojo/services/public/cpp/view_manager/view_manager.h"
#include "mojo/services/public/cpp/view_manager/view_manager_delegate.h"
#include "mojo/services/public/cpp/view_manager/view_observer.h"
#include "mojo/services/public/cpp/view_manager/view_tree_node.h"
#include "mojo/services/public/cpp/view_manager/view_tree_node_observer.h"
......@@ -15,6 +16,7 @@
using mojo::view_manager::View;
using mojo::view_manager::ViewManager;
using mojo::view_manager::ViewManagerDelegate;
using mojo::view_manager::ViewObserver;
using mojo::view_manager::ViewTreeNode;
using mojo::view_manager::ViewTreeNodeObserver;
......@@ -31,21 +33,38 @@ const SkColor kColors[] = { SK_ColorYELLOW,
} // namespace
class EmbeddedApp : public Application,
public ViewManagerDelegate,
public ViewObserver,
public ViewTreeNodeObserver {
public:
EmbeddedApp() : view_manager_(NULL) {}
EmbeddedApp() {}
virtual ~EmbeddedApp() {}
private:
// Overridden from Application:
virtual void Initialize() MOJO_OVERRIDE {
ViewManager::Create(this,
base::Bind(&EmbeddedApp::OnRootAdded, base::Unretained(this)),
base::Bind(&EmbeddedApp::OnRootRemoved, base::Unretained(this)));
ViewManager::Create(this, this);
ConnectTo<IWindowManager>("mojo:mojo_window_manager", &window_manager_);
}
// Overridden from ViewManagerDelegate:
virtual void OnRootAdded(ViewManager* view_manager,
ViewTreeNode* root) OVERRIDE {
View* view = View::Create(view_manager);
view->AddObserver(this);
root->SetActiveView(view);
root->AddObserver(this);
size_t index = view_manager->roots().size() - 1;
view->SetColor(kColors[index % arraysize(kColors)]);
}
virtual void OnRootRemoved(ViewManager* view_manager,
ViewTreeNode* root) OVERRIDE {
std::map<ViewTreeNode*, View*>::const_iterator it =
views_to_reap_.find(root);
if (it != views_to_reap_.end())
it->second->Destroy();
}
// Overridden from ViewObserver:
virtual void OnViewInputEvent(View* view, EventPtr event) OVERRIDE {
if (event->action == ui::ET_MOUSE_RELEASED)
......@@ -62,29 +81,7 @@ class EmbeddedApp : public Application,
views_to_reap_[node] = old_view;
}
void OnRootAdded(ViewManager* view_manager, ViewTreeNode* root) {
if (!view_manager_)
view_manager_ = view_manager;
DCHECK_EQ(view_manager_, view_manager);
View* view = View::Create(view_manager_);
view->AddObserver(this);
root->SetActiveView(view);
root->AddObserver(this);
size_t index = view_manager_->roots().size() - 1;
view->SetColor(kColors[index % arraysize(kColors)]);
}
void OnRootRemoved(ViewManager* view_manager,
ViewTreeNode* root) {
std::map<ViewTreeNode*, View*>::const_iterator it =
views_to_reap_.find(root);
if (it != views_to_reap_.end())
it->second->Destroy();
}
IWindowManagerPtr window_manager_;
ViewManager* view_manager_;
std::map<ViewTreeNode*, View*> views_to_reap_;
DISALLOW_COPY_AND_ASSIGN(EmbeddedApp);
......
include_rules = [
"+ui/events",
]
// 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 "base/basictypes.h"
#include "base/bind.h"
#include "mojo/examples/window_manager/window_manager.mojom.h"
#include "mojo/public/cpp/application/application.h"
#include "mojo/services/public/cpp/view_manager/view.h"
#include "mojo/services/public/cpp/view_manager/view_manager.h"
#include "mojo/services/public/cpp/view_manager/view_manager_delegate.h"
#include "mojo/services/public/cpp/view_manager/view_observer.h"
#include "mojo/services/public/cpp/view_manager/view_tree_node.h"
#include "mojo/services/public/cpp/view_manager/view_tree_node_observer.h"
#include "ui/events/event_constants.h"
using mojo::view_manager::View;
using mojo::view_manager::ViewManager;
using mojo::view_manager::ViewManagerDelegate;
using mojo::view_manager::ViewObserver;
using mojo::view_manager::ViewTreeNode;
using mojo::view_manager::ViewTreeNodeObserver;
namespace mojo {
namespace examples {
// An app that embeds another app.
class NestingApp : public Application,
public ViewManagerDelegate,
public ViewObserver {
public:
NestingApp() {}
virtual ~NestingApp() {}
private:
// Overridden from Application:
virtual void Initialize() MOJO_OVERRIDE {
ViewManager::Create(this, this);
ConnectTo<IWindowManager>("mojo:mojo_window_manager", &window_manager_);
}
// Overridden from ViewManagerDelegate:
virtual void OnRootAdded(ViewManager* view_manager,
ViewTreeNode* root) OVERRIDE {
View* view = View::Create(view_manager);
root->SetActiveView(view);
view->SetColor(SK_ColorCYAN);
view->AddObserver(this);
ViewTreeNode* nested = ViewTreeNode::Create(view_manager);
root->AddChild(nested);
nested->SetBounds(gfx::Rect(20, 20, 50, 50));
nested->Embed("mojo:mojo_embedded_app");
}
virtual void OnRootRemoved(ViewManager* view_manager,
ViewTreeNode* root) OVERRIDE {
// TODO(beng): reap views & child nodes.
}
// Overridden from ViewObserver:
virtual void OnViewInputEvent(View* view, EventPtr event) OVERRIDE {
if (event->action == ui::ET_MOUSE_RELEASED)
window_manager_->CloseWindow(view->node()->id());
}
IWindowManagerPtr window_manager_;
DISALLOW_COPY_AND_ASSIGN(NestingApp);
};
} // namespace examples
// static
Application* Application::Create() {
return new examples::NestingApp;
}
} // namespace mojo
\ No newline at end of file
......@@ -8,6 +8,7 @@
#include "mojo/public/cpp/application/application.h"
#include "mojo/services/public/cpp/view_manager/view.h"
#include "mojo/services/public/cpp/view_manager/view_manager.h"
#include "mojo/services/public/cpp/view_manager/view_manager_delegate.h"
#include "mojo/services/public/cpp/view_manager/view_observer.h"
#include "mojo/services/public/cpp/view_manager/view_tree_node.h"
#include "ui/events/event_constants.h"
......@@ -16,6 +17,14 @@
#undef CreateWindow
#endif
using mojo::view_manager::TransportNodeId;
using mojo::view_manager::View;
using mojo::view_manager::ViewManager;
using mojo::view_manager::ViewManagerDelegate;
using mojo::view_manager::ViewObserver;
using mojo::view_manager::ViewTreeNode;
using mojo::view_manager::ViewTreeNodeObserver;
namespace mojo {
namespace examples {
......@@ -29,7 +38,7 @@ class WindowManagerConnection : public InterfaceImpl<IWindowManager> {
private:
// Overridden from IWindowManager:
virtual void CloseWindow(view_manager::TransportNodeId node_id) OVERRIDE;
virtual void CloseWindow(TransportNodeId node_id) OVERRIDE;
WindowManager* window_manager_;
......@@ -37,14 +46,14 @@ class WindowManagerConnection : public InterfaceImpl<IWindowManager> {
};
class WindowManager : public Application,
public view_manager::ViewObserver {
public ViewObserver,
public ViewManagerDelegate {
public:
WindowManager() {}
WindowManager() : view_manager_(NULL) {}
virtual ~WindowManager() {}
void CloseWindow(view_manager::TransportNodeId node_id) {
DCHECK(view_manager_);
view_manager::ViewTreeNode* node = view_manager_->GetNodeById(node_id);
void CloseWindow(TransportNodeId node_id) {
ViewTreeNode* node = view_manager_->GetNodeById(node_id);
DCHECK(node);
node->Destroy();
}
......@@ -53,30 +62,38 @@ class WindowManager : public Application,
// Overridden from Application:
virtual void Initialize() MOJO_OVERRIDE {
AddService<WindowManagerConnection>(this);
ViewManager::Create(this, this);
}
// Overridden from ViewObserver:
virtual void OnViewInputEvent(View* view, EventPtr event) OVERRIDE {
if (event->action == ui::ET_MOUSE_RELEASED) {
if (event->flags & ui::EF_LEFT_MOUSE_BUTTON)
CreateWindow("mojo:mojo_embedded_app");
else if (event->flags & ui::EF_RIGHT_MOUSE_BUTTON)
CreateWindow("mojo:mojo_nesting_app");
}
}
// Overridden from ViewManagerDelegate:
virtual void OnRootAdded(ViewManager* view_manager,
ViewTreeNode* root) OVERRIDE {
DCHECK(!view_manager_);
view_manager_ = view_manager;
view_manager_ = view_manager::ViewManager::CreateBlocking(this);
view_manager::ViewTreeNode* node =
view_manager::ViewTreeNode::Create(view_manager_);
view_manager_->roots().front()->AddChild(node);
ViewTreeNode* node = ViewTreeNode::Create(view_manager);
view_manager->roots().front()->AddChild(node);
node->SetBounds(gfx::Rect(800, 600));
parent_node_id_ = node->id();
view_manager::View* view = view_manager::View::Create(view_manager_);
View* view = View::Create(view_manager);
node->SetActiveView(view);
view->SetColor(SK_ColorBLUE);
view->AddObserver(this);
}
// Overridden from ViewObserver:
virtual void OnViewInputEvent(view_manager::View* view,
EventPtr event) OVERRIDE {
if (event->action == ui::ET_MOUSE_RELEASED)
CreateWindow();
}
void CreateWindow() {
view_manager::ViewTreeNode* node =
view_manager_->GetNodeById(parent_node_id_);
void CreateWindow(const String& url) {
ViewTreeNode* node = view_manager_->GetNodeById(parent_node_id_);
gfx::Rect bounds(50, 50, 200, 200);
if (!node->children().empty()) {
......@@ -85,21 +102,19 @@ class WindowManager : public Application,
bounds.set_origin(position);
}
view_manager::ViewTreeNode* embedded =
view_manager::ViewTreeNode::Create(view_manager_);
ViewTreeNode* embedded = ViewTreeNode::Create(view_manager_);
node->AddChild(embedded);
embedded->SetBounds(bounds);
embedded->Embed("mojo:mojo_embedded_app");
embedded->Embed(url);
}
view_manager::ViewManager* view_manager_;
view_manager::TransportNodeId parent_node_id_;
ViewManager* view_manager_;
TransportNodeId parent_node_id_;
DISALLOW_COPY_AND_ASSIGN(WindowManager);
};
void WindowManagerConnection::CloseWindow(
view_manager::TransportNodeId node_id) {
void WindowManagerConnection::CloseWindow(TransportNodeId node_id) {
window_manager_->CloseWindow(node_id);
}
......
......@@ -68,6 +68,7 @@
'mojo_aura_demo_init',
'mojo_demo_launcher',
'mojo_embedded_app',
'mojo_nesting_app',
'mojo_window_manager',
'mojo_view_manager',
'mojo_view_manager_unittests',
......
......@@ -323,6 +323,28 @@
'public/cpp/application/lib/mojo_main_chromium.cc',
],
},
{
'target_name': 'mojo_nesting_app',
'type': 'shared_library',
'dependencies': [
'../base/base.gyp:base',
'../ui/gfx/gfx.gyp:gfx_geometry',
'../ui/gl/gl.gyp:gl',
'mojo_application',
'mojo_cpp_bindings',
'mojo_environment_chromium',
'mojo_geometry_bindings',
'mojo_gles2',
'mojo_view_manager_lib',
'mojo_window_manager_bindings',
'mojo_system_impl',
'mojo_utility',
],
'sources': [
'examples/nesting_app/nesting_app.cc',
'public/cpp/application/lib/mojo_main_chromium.cc',
],
},
],
}],
['OS=="linux"', {
......
......@@ -278,6 +278,7 @@
'services/public/cpp/view_manager/lib/view_tree_node_private.h',
'services/public/cpp/view_manager/view.h',
'services/public/cpp/view_manager/view_manager.h',
'services/public/cpp/view_manager/view_manager_delegate.h',
'services/public/cpp/view_manager/view_manager_types.h',
'services/public/cpp/view_manager/view_observer.h',
'services/public/cpp/view_manager/view_tree_host.h',
......
......@@ -14,15 +14,6 @@
namespace mojo {
namespace view_manager {
namespace {
void OnViewManagerReady(base::RunLoop* loop,
ViewManager* manager,
ViewTreeNode* root) {
loop->Quit();
}
} // namespace
////////////////////////////////////////////////////////////////////////////////
// ViewManager, public:
......@@ -45,22 +36,9 @@ ViewManager::~ViewManager() {
}
// static
ViewManager* ViewManager::CreateBlocking(Application* application) {
base::RunLoop init_loop;
ViewManager* manager = new ViewManager(
application,
base::Bind(&OnViewManagerReady, &init_loop),
RootCallback());
init_loop.Run();
return manager;
}
// static
void ViewManager::Create(
Application* application,
const RootCallback& root_added_callback,
const RootCallback& root_removed_callback) {
new ViewManager(application, root_added_callback, root_removed_callback);
void ViewManager::Create(Application* application,
ViewManagerDelegate* delegate) {
application->AddService<ViewManagerSynchronizer>(delegate);
}
ViewTreeNode* ViewManager::GetNodeById(TransportNodeId id) {
......@@ -76,15 +54,10 @@ View* ViewManager::GetViewById(TransportViewId id) {
////////////////////////////////////////////////////////////////////////////////
// ViewManager, private:
ViewManager::ViewManager(
Application* application,
const RootCallback& root_added_callback,
const RootCallback& root_removed_callback)
: root_added_callback_(root_added_callback),
root_removed_callback_(root_removed_callback),
synchronizer_(NULL) {
application->AddService<ViewManagerSynchronizer>(this);
}
ViewManager::ViewManager(ViewManagerSynchronizer* synchronizer,
ViewManagerDelegate* delegate)
: delegate_(delegate),
synchronizer_(synchronizer) {}
} // namespace view_manager
} // namespace mojo
......@@ -5,6 +5,7 @@
#include "mojo/services/public/cpp/view_manager/lib/view_manager_private.h"
#include "mojo/services/public/cpp/view_manager/lib/view_tree_node_private.h"
#include "mojo/services/public/cpp/view_manager/view_manager_delegate.h"
#include "mojo/services/public/cpp/view_manager/view_tree_node_observer.h"
namespace mojo {
......@@ -50,8 +51,7 @@ void ViewManagerPrivate::AddRoot(ViewTreeNode* root) {
}
manager_->roots_.push_back(root);
root->AddObserver(new RootObserver(root));
if (!manager_->root_added_callback_.is_null())
manager_->root_added_callback_.Run(manager_, root);
manager_->delegate_->OnRootAdded(manager_, root);
}
void ViewManagerPrivate::RemoveRoot(ViewTreeNode* root) {
......@@ -59,8 +59,7 @@ void ViewManagerPrivate::RemoveRoot(ViewTreeNode* root) {
std::find(manager_->roots_.begin(), manager_->roots_.end(), root);
if (it != manager_->roots_.end()) {
manager_->roots_.erase(it);
if (!manager_->root_removed_callback_.is_null())
manager_->root_removed_callback_.Run(manager_, root);
manager_->delegate_->OnRootRemoved(manager_, root);
}
}
......
......@@ -437,18 +437,16 @@ class EmbedTransaction : public ViewManagerTransaction {
DISALLOW_COPY_AND_ASSIGN(EmbedTransaction);
};
ViewManagerSynchronizer::ViewManagerSynchronizer(ViewManager* view_manager)
: view_manager_(view_manager),
ViewManagerSynchronizer::ViewManagerSynchronizer(ViewManagerDelegate* delegate)
: view_manager_(new ViewManager(this, delegate)),
connected_(false),
connection_id_(0),
next_id_(1),
next_server_change_id_(0),
sync_factory_(this) {
ViewManagerPrivate(view_manager).set_synchronizer(this);
}
ViewManagerSynchronizer::~ViewManagerSynchronizer() {
view_manager_.reset();
}
TransportNodeId ViewManagerSynchronizer::CreateViewTreeNode() {
......@@ -652,7 +650,6 @@ void ViewManagerSynchronizer::OnViewInputEvent(
ack_callback.Run();
}
////////////////////////////////////////////////////////////////////////////////
// ViewManagerSynchronizer, private:
......
......@@ -10,6 +10,7 @@
#include "base/memory/scoped_vector.h"
#include "base/memory/weak_ptr.h"
#include "mojo/services/public/cpp/geometry/geometry_type_converters.h"
#include "mojo/services/public/cpp/view_manager/view_manager.h"
#include "mojo/services/public/cpp/view_manager/view_manager_types.h"
#include "mojo/services/public/interfaces/view_manager/view_manager.mojom.h"
......@@ -24,10 +25,11 @@ class ViewManagerTransaction;
// Manages the connection with the View Manager service.
class ViewManagerSynchronizer : public InterfaceImpl<IViewManagerClient> {
public:
explicit ViewManagerSynchronizer(ViewManager* view_manager);
explicit ViewManagerSynchronizer(ViewManagerDelegate* delegate);
virtual ~ViewManagerSynchronizer();
bool connected() const { return connected_; }
TransportConnectionId connection_id() const { return connection_id_; }
// API exposed to the node/view implementations that pushes local changes to
// the service.
......
......@@ -14,6 +14,7 @@
#include "mojo/services/public/cpp/view_manager/lib/view_tree_node_private.h"
#include "mojo/services/public/cpp/view_manager/util.h"
#include "mojo/services/public/cpp/view_manager/view.h"
#include "mojo/services/public/cpp/view_manager/view_manager_delegate.h"
#include "mojo/services/public/cpp/view_manager/view_observer.h"
#include "mojo/services/public/cpp/view_manager/view_tree_node_observer.h"
#include "mojo/shell/shell_test_helper.h"
......@@ -50,10 +51,14 @@ void WaitForAllChangesToBeAcked(ViewManager* manager) {
ViewManagerPrivate(manager).synchronizer()->ClearChangesAckedCallback();
}
class ConnectServiceLoader : public ServiceLoader {
class ConnectServiceLoader : public ServiceLoader,
public ViewManagerDelegate {
public:
explicit ConnectServiceLoader(const ViewManager::RootCallback& callback)
: callback_(callback) {}
typedef base::Callback<void(ViewManager*, ViewTreeNode*)> LoadedCallback;
explicit ConnectServiceLoader(const LoadedCallback& callback)
: callback_(callback) {
}
virtual ~ConnectServiceLoader() {}
private:
......@@ -62,16 +67,21 @@ class ConnectServiceLoader : public ServiceLoader {
const GURL& url,
ScopedMessagePipeHandle shell_handle) OVERRIDE {
scoped_ptr<Application> app(new Application(shell_handle.Pass()));
// TODO(beng): test removed callback.
ViewManager::Create(app.get(), callback_, ViewManager::RootCallback());
ViewManager::Create(app.get(), this);
apps_.push_back(app.release());
}
virtual void OnServiceError(ServiceManager* manager,
const GURL& url) OVERRIDE {
}
// Overridden from ViewManagerDelegate:
virtual void OnRootAdded(ViewManager* view_manager,
ViewTreeNode* root) OVERRIDE {
callback_.Run(view_manager, root);
}
ScopedVector<Application> apps_;
ViewManager::RootCallback callback_;
LoadedCallback callback_;
DISALLOW_COPY_AND_ASSIGN(ConnectServiceLoader);
};
......@@ -328,7 +338,7 @@ class ViewManagerTest : public testing::Test {
private:
// Overridden from testing::Test:
virtual void SetUp() OVERRIDE {
ViewManager::RootCallback ready_callback =
ConnectServiceLoader::LoadedCallback ready_callback =
base::Bind(&ViewManagerTest::OnViewManagerLoaded,
base::Unretained(this));
test_helper_.Init();
......
......@@ -18,28 +18,19 @@ class Application;
namespace view_manager {
class View;
class ViewManagerDelegate;
class ViewManagerSynchronizer;
class ViewTreeNode;
// Approximately encapsulates the View Manager service.
// Has a synchronizer that keeps a client model in sync with the service.
// Owned by the connection.
//
// TODO: displays
class ViewManager {
public:
typedef base::Callback<void(ViewManager*, ViewTreeNode*)> RootCallback;
~ViewManager();
// |ready_callback| is run when the ViewManager connection is established
// and ready to use.
static void Create(
Application* application,
const RootCallback& root_added_callback,
const RootCallback& root_removed_callback);
// Blocks until ViewManager is ready to use.
static ViewManager* CreateBlocking(Application* application);
// Delegate is owned by the caller.
static void Create(Application* application, ViewManagerDelegate* delegate);
const std::vector<ViewTreeNode*>& roots() { return roots_; }
......@@ -48,16 +39,17 @@ class ViewManager {
private:
friend class ViewManagerPrivate;
friend class ViewManagerSynchronizer;
typedef std::map<TransportNodeId, ViewTreeNode*> IdToNodeMap;
typedef std::map<TransportViewId, View*> IdToViewMap;
typedef std::map<TransportConnectionId,
ViewManagerSynchronizer*> SynchronizerMap;
ViewManager(Application* application,
const RootCallback& root_added_callback,
const RootCallback& root_removed_callback);
RootCallback root_added_callback_;
RootCallback root_removed_callback_;
ViewManager(ViewManagerSynchronizer* synchronizer,
ViewManagerDelegate* delegate);
ViewManagerDelegate* delegate_;
ViewManagerSynchronizer* synchronizer_;
std::vector<ViewTreeNode*> roots_;
......
// 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.
#ifndef MOJO_SERVICES_PUBLIC_CPP_VIEW_MANAGER_VIEW_MANAGER_DELEGATE_H_
#define MOJO_SERVICES_PUBLIC_CPP_VIEW_MANAGER_VIEW_MANAGER_DELEGATE_H_
namespace mojo {
namespace view_manager {
class ViewManager;
class ViewTreeNode;
class ViewManagerDelegate {
public:
virtual void OnRootAdded(ViewManager* view_manager, ViewTreeNode* root) {}
virtual void OnRootRemoved(ViewManager* view_manager, ViewTreeNode* root) {}
protected:
virtual ~ViewManagerDelegate() {}
};
} // namespace view_manager
} // namespace mojo
#endif // MOJO_SERVICES_PUBLIC_CPP_VIEW_MANAGER_VIEW_MANAGER_DELEGATE_H_
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment