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

Allow EmbedRoot to be called multiple times.

Subsequent calls to EmbedRoot are now delegated to the window manager. This allows an application that was not created via the embed flow to obtain a connection to the view manager by asking the view manager init service to embed it somewhere. The init service just forwards this to the window manager. This is effectively like asking the window manager to create a toplevel window.

R=sky@chromium.org
BUG=none

Committed: https://src.chromium.org/viewvc/chrome?view=rev&revision=284322

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

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@284624 0039d316-1c4b-4281-b951-d872f2087c98
parent fcee6820
......@@ -15,9 +15,9 @@
#include "mojo/services/public/cpp/view_manager/node.h"
#include "mojo/services/public/cpp/view_manager/node_observer.h"
#include "mojo/services/public/cpp/view_manager/view.h"
#include "mojo/services/public/cpp/view_manager/view_event_dispatcher.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/window_manager_delegate.h"
#include "mojo/services/public/interfaces/input_events/input_events.mojom.h"
#include "mojo/services/public/interfaces/launcher/launcher.mojom.h"
#include "mojo/services/public/interfaces/navigation/navigation.mojom.h"
......@@ -34,10 +34,10 @@ using mojo::view_manager::Id;
using mojo::view_manager::Node;
using mojo::view_manager::NodeObserver;
using mojo::view_manager::View;
using mojo::view_manager::ViewEventDispatcher;
using mojo::view_manager::ViewManager;
using mojo::view_manager::ViewManagerDelegate;
using mojo::view_manager::ViewObserver;
using mojo::view_manager::WindowManagerDelegate;
namespace mojo {
namespace examples {
......@@ -252,7 +252,7 @@ class RootLayoutManager : public NodeObserver {
class WindowManager : public ApplicationDelegate,
public DebugPanel::Delegate,
public ViewManagerDelegate,
public ViewEventDispatcher {
public WindowManagerDelegate {
public:
WindowManager()
: launcher_ui_(NULL),
......@@ -339,7 +339,7 @@ class WindowManager : public ApplicationDelegate,
virtual void OnRootAdded(ViewManager* view_manager, Node* root) OVERRIDE {
DCHECK(!view_manager_);
view_manager_ = view_manager;
view_manager_->SetEventDispatcher(this);
view_manager_->SetWindowManagerDelegate(this);
Node* node = Node::Create(view_manager_);
root->AddChild(node);
......@@ -366,7 +366,12 @@ class WindowManager : public ApplicationDelegate,
base::MessageLoop::current()->Quit();
}
// Overridden from ViewEventDispatcher:
// Overridden from WindowManagerDelegate:
virtual void EmbedRoot(const String& url) OVERRIDE {
CreateWindow(url,
navigation::NavigationDetailsPtr().Pass(),
navigation::ResponseDetailsPtr().Pass());
}
virtual void DispatchEvent(View* target, EventPtr event) OVERRIDE {
// TODO(beng): More sophisticated focus handling than this is required!
if (event->action == ui::ET_MOUSE_PRESSED &&
......
......@@ -522,10 +522,10 @@
'services/public/cpp/view_manager/node.h',
'services/public/cpp/view_manager/node_observer.h',
'services/public/cpp/view_manager/view.h',
'services/public/cpp/view_manager/view_event_dispatcher.h',
'services/public/cpp/view_manager/view_manager.h',
'services/public/cpp/view_manager/view_manager_delegate.h',
'services/public/cpp/view_manager/view_observer.h',
'services/public/cpp/view_manager/window_manager_delegate.h',
],
'export_dependent_settings': [
'mojo_view_manager_bindings',
......
......@@ -13,9 +13,9 @@
#include "mojo/services/public/cpp/view_manager/lib/view_private.h"
#include "mojo/services/public/cpp/view_manager/node_observer.h"
#include "mojo/services/public/cpp/view_manager/util.h"
#include "mojo/services/public/cpp/view_manager/view_event_dispatcher.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/window_manager_delegate.h"
#include "third_party/skia/include/core/SkBitmap.h"
#include "ui/gfx/codec/png_codec.h"
......@@ -529,7 +529,7 @@ ViewManagerClientImpl::ViewManagerClientImpl(ApplicationConnection* connection,
connection_id_(0),
next_id_(1),
delegate_(delegate),
dispatcher_(NULL) {}
window_manager_delegate_(NULL) {}
ViewManagerClientImpl::~ViewManagerClientImpl() {
while (!nodes_.empty()) {
......@@ -676,14 +676,14 @@ void ViewManagerClientImpl::RemoveView(Id view_id) {
////////////////////////////////////////////////////////////////////////////////
// ViewManagerClientImpl, ViewManager implementation:
void ViewManagerClientImpl::SetEventDispatcher(
ViewEventDispatcher* dispatcher) {
void ViewManagerClientImpl::SetWindowManagerDelegate(
WindowManagerDelegate* window_manager_delegate) {
CHECK(NULL != GetNodeById(1));
dispatcher_ = dispatcher;
window_manager_delegate_ = window_manager_delegate;
}
void ViewManagerClientImpl::DispatchEvent(View* target, EventPtr event) {
CHECK(dispatcher_);
CHECK(window_manager_delegate_);
service_->DispatchOnViewInputEvent(target->id(), event.Pass());
}
......@@ -824,9 +824,13 @@ void ViewManagerClientImpl::OnFocusChanged(Id gained_focus_id,
}
}
void ViewManagerClientImpl::EmbedRoot(const String& url) {
window_manager_delegate_->EmbedRoot(url);
}
void ViewManagerClientImpl::DispatchOnViewInputEvent(Id view_id,
EventPtr event) {
dispatcher_->DispatchEvent(GetViewById(view_id), event.Pass());
window_manager_delegate_->DispatchEvent(GetViewById(view_id), event.Pass());
}
////////////////////////////////////////////////////////////////////////////////
......
......@@ -21,7 +21,6 @@ namespace mojo {
class ApplicationConnection;
namespace view_manager {
class ViewEventDispatcher;
class ViewManager;
class ViewManagerTransaction;
......@@ -88,7 +87,8 @@ class ViewManagerClientImpl : public ViewManager,
typedef std::map<Id, View*> IdToViewMap;
// Overridden from ViewManager:
virtual void SetEventDispatcher(ViewEventDispatcher* dispatcher) OVERRIDE;
virtual void SetWindowManagerDelegate(
WindowManagerDelegate* delegate) OVERRIDE;
virtual void DispatchEvent(View* target, EventPtr event) OVERRIDE;
virtual const std::string& GetEmbedderURL() const OVERRIDE;
virtual const std::vector<Node*>& GetRoots() const OVERRIDE;
......@@ -123,6 +123,7 @@ class ViewManagerClientImpl : public ViewManager,
EventPtr event,
const Callback<void()>& callback) OVERRIDE;
virtual void OnFocusChanged(Id gained_focus_id, Id lost_focus_id) OVERRIDE;
virtual void EmbedRoot(const String& url) OVERRIDE;
virtual void DispatchOnViewInputEvent(Id view_id, EventPtr event) OVERRIDE;
// Sync the client model with the service by enumerating the pending
......@@ -147,7 +148,7 @@ class ViewManagerClientImpl : public ViewManager,
base::Callback<void(void)> changes_acked_callback_;
ViewManagerDelegate* delegate_;
ViewEventDispatcher* dispatcher_;
WindowManagerDelegate* window_manager_delegate_;
std::vector<Node*> roots_;
......
......@@ -17,8 +17,8 @@ namespace view_manager {
class Node;
class View;
class ViewEventDispatcher;
class ViewManagerDelegate;
class WindowManagerDelegate;
class ViewManager {
public:
......@@ -26,12 +26,13 @@ class ViewManager {
static void ConfigureIncomingConnection(ApplicationConnection* connection,
ViewManagerDelegate* delegate);
// Sets the event dispatcher. Can only be called by the app rendering to the
// root Node of the hierarchy.
virtual void SetEventDispatcher(ViewEventDispatcher* dispatcher) = 0;
// Sets the window manager delegate. Can only be called by the app embedded at
// the service root node.
virtual void SetWindowManagerDelegate(
WindowManagerDelegate* window_manager_delegate) = 0;
// Dispatches the supplied event to the specified View. Can be called only
// by the application that called SetEventDispatcher().
// by the application that called SetWindowManagerDelegate().
virtual void DispatchEvent(View* target, EventPtr event) = 0;
// Returns the URL of the application that embedded this application.
......
......@@ -2,8 +2,8 @@
// 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_EVENT_DISPATCHER_H_
#define MOJO_SERVICES_PUBLIC_CPP_VIEW_MANAGER_VIEW_EVENT_DISPATCHER_H_
#ifndef MOJO_SERVICES_PUBLIC_CPP_VIEW_MANAGER_WINDOW_MANAGER_DELEGATE_H_
#define MOJO_SERVICES_PUBLIC_CPP_VIEW_MANAGER_WINDOW_MANAGER_DELEGATE_H_
#include "mojo/services/public/interfaces/input_events/input_events.mojom.h"
......@@ -12,19 +12,22 @@ namespace view_manager {
class View;
// A ViewEventDispatcher is provided by the application rendering at the root
// of a Node hierarchy. It is responsible for targeting input events to the
// relevant Views. This allows window manager features like focus, activation,
// modality, etc. to be implemented.
class ViewEventDispatcher {
// A WindowManagerDelegate is provided by the application embedded at the
// service root node.
class WindowManagerDelegate {
public:
// Create an appropriate node to embed |url|.
virtual void EmbedRoot(const String& url) = 0;
// Dispatch the supplied input event to the appropriate view (taking into
// account focus, activation, modality, etc.).
virtual void DispatchEvent(View* target, EventPtr event) = 0;
protected:
virtual ~ViewEventDispatcher() {}
virtual ~WindowManagerDelegate() {}
};
} // namespace view_manager
} // namespace mojo
#endif // MOJO_SERVICES_PUBLIC_CPP_VIEW_MANAGER_VIEW_EVENT_DISPATCHER_H_
#endif // MOJO_SERVICES_PUBLIC_CPP_VIEW_MANAGER_WINDOW_MANAGER_DELEGATE_H_
......@@ -22,10 +22,17 @@ enum ErrorCode {
ILLEGAL_ARGUMENT,
};
// ViewManagerInitService is responsible for launching the client that controls
// the root node. mojo::view_manager returns an instance of this. All other
// connections are established by the client this creates.
// ViewManagerInitService is used to grant an application a connection to the
// ViewManager by embedding it at an approriate Node.
interface ViewManagerInitService {
// Embed the application @ |url| at an appropriate Node.
// The first time this method is called in the lifetime of a View Manager
// application instance, the "appropriate Node" is defined as being the
// service root Node.
// Subsequent times, implementation of this method is delegated to the
// application embedded at the service root Node. This application is
// typically referred to as the "window manager", and will have a specific
// definition of where within its Node hierarchy to embed an unparented URL.
EmbedRoot(string url) => (bool success);
};
......@@ -193,8 +200,16 @@ interface ViewManagerClient {
// removed.
OnFocusChanged(uint32 gained_focus_id, uint32 lost_focus_id);
// TODO(sky): move to separate interface when FIFO sorted out.
// TODO(sky): The following methods represent an interface between the view
// manager and the application embedded at the service root node
// (i.e. the window manager). These methods are not called on
// any other clients. They should be moved to a separate interface
// once support for derived FIFOs is landed.
// Requests the window manager create a "top level" node embedding |url|.
EmbedRoot(string url);
// Requests the view manager dispatch the event targeted at |view|.
DispatchOnViewInputEvent(uint32 view, mojo.Event event);
};
......
......@@ -88,8 +88,12 @@ void RootNodeManager::RemoveConnection(ViewManagerServiceImpl* connection) {
}
void RootNodeManager::EmbedRoot(const std::string& url) {
CHECK(connection_map_.empty());
if (connection_map_.empty()) {
EmbedImpl(kRootConnection, String::From(url), InvalidNodeId());
return;
}
ViewManagerServiceImpl* connection = GetConnection(kWindowManagerConnection);
connection->client()->EmbedRoot(url);
}
void RootNodeManager::Embed(ConnectionSpecificId creator_id,
......
......@@ -80,6 +80,8 @@ std::string ChangeToDescription1(const Change& change) {
"InputEvent view=%s event_action=%d",
NodeIdToString(change.view_id).c_str(),
change.event_action);
case CHANGE_TYPE_EMBED_ROOT:
return base::StringPrintf("EmbedRoot url=%s", change.embed_url.data());
}
return std::string();
}
......@@ -223,6 +225,13 @@ void TestChangeTracker::OnViewInputEvent(Id view_id, EventPtr event) {
AddChange(change);
}
void TestChangeTracker::OnEmbedRoot(const String& url) {
Change change;
change.type = CHANGE_TYPE_EMBED_ROOT;
change.embed_url = url;
AddChange(change);
}
void TestChangeTracker::AddChange(const Change& change) {
changes_.push_back(change);
if (delegate_)
......
......@@ -27,6 +27,7 @@ enum ChangeType {
CHANGE_TYPE_VIEW_DELETED,
CHANGE_TYPE_VIEW_REPLACED,
CHANGE_TYPE_INPUT_EVENT,
CHANGE_TYPE_EMBED_ROOT,
};
// TODO(sky): consider nuking and converting directly to NodeData.
......@@ -57,6 +58,7 @@ struct Change {
gfx::Rect bounds2;
int32 event_action;
String creator_url;
String embed_url;
OrderDirection direction;
};
......@@ -111,6 +113,7 @@ class TestChangeTracker {
void OnViewDeleted(Id view_id);
void OnNodeViewReplaced(Id node_id, Id new_view_id, Id old_view_id);
void OnViewInputEvent(Id view_id, EventPtr event);
void OnEmbedRoot(const String& url);
private:
void AddChange(const Change& change);
......
......@@ -44,11 +44,8 @@ void ViewManagerInitServiceImpl::MaybeEmbedRoot(
void ViewManagerInitServiceImpl::EmbedRoot(
const String& url,
const Callback<void(bool)>& callback) {
if (connect_params_) {
DVLOG(1) << "Ignoring second connect";
callback.Run(false);
return;
}
// TODO(beng): This means you can only have one EmbedRoot in flight at a time.
// Keep a vector of these around instead.
connect_params_.reset(new ConnectParams);
connect_params_->url = url.To<std::string>();
connect_params_->callback = callback;
......
......@@ -318,7 +318,7 @@ class TestViewManagerClientConnection
connection_.set_view_manager(client());
}
// ViewMangerClient:
// ViewManagerClient:
virtual void OnViewManagerConnectionEstablished(
ConnectionSpecificId connection_id,
const String& creator_url,
......@@ -363,6 +363,9 @@ class TestViewManagerClientConnection
}
virtual void OnFocusChanged(Id gained_focus_id,
Id lost_focus_id) OVERRIDE {}
virtual void EmbedRoot(const String& url) OVERRIDE {
tracker_.OnEmbedRoot(url);
}
virtual void DispatchOnViewInputEvent(Id view_id,
mojo::EventPtr event) OVERRIDE {
}
......@@ -517,6 +520,12 @@ class ViewManagerTest : public testing::Test {
DISALLOW_COPY_AND_ASSIGN(ViewManagerTest);
};
TEST_F(ViewManagerTest, SecondEmbedRoot) {
ASSERT_TRUE(EmbedRoot(view_manager_init_.get(), kTestServiceURL));
connection_->DoRunLoopUntilChangesCount(1);
EXPECT_EQ(kTestServiceURL, connection_->changes()[0].embed_url);
}
// Verifies client gets a valid id.
TEST_F(ViewManagerTest, ValidId) {
// TODO(beng): this should really have the URL of the application that
......
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