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 "base/basictypes.h"
6 #include "base/bind.h"
7 #include "base/strings/stringprintf.h"
8 #include "mojo/examples/window_manager/window_manager.mojom.h"
9 #include "mojo/public/cpp/application/application.h"
10 #include "mojo/services/public/cpp/view_manager/node.h"
11 #include "mojo/services/public/cpp/view_manager/view.h"
12 #include "mojo/services/public/cpp/view_manager/view_manager.h"
13 #include "mojo/services/public/cpp/view_manager/view_manager_delegate.h"
14 #include "mojo/services/public/cpp/view_manager/view_observer.h"
15 #include "mojo/services/public/interfaces/launcher/launcher.mojom.h"
16 #include "mojo/services/public/interfaces/navigation/navigation.mojom.h"
17 #include "ui/events/event_constants.h"
18
19 #if defined CreateWindow
20 #undef CreateWindow
21 #endif
22
23 using mojo::view_manager::Id;
24 using mojo::view_manager::Node;
25 using mojo::view_manager::NodeObserver;
26 using mojo::view_manager::View;
27 using mojo::view_manager::ViewManager;
28 using mojo::view_manager::ViewManagerDelegate;
29 using mojo::view_manager::ViewObserver;
30
31 namespace mojo {
32 namespace examples {
33
34 class WindowManager;
35
36 namespace {
37
38 const SkColor kColors[] = { SK_ColorYELLOW,
39 SK_ColorRED,
40 SK_ColorGREEN,
41 SK_ColorMAGENTA };
42
43 } // namespace
44
45 class WindowManagerConnection : public InterfaceImpl<IWindowManager> {
46 public:
WindowManagerConnection(WindowManager * window_manager)47 explicit WindowManagerConnection(WindowManager* window_manager)
48 : window_manager_(window_manager) {}
~WindowManagerConnection()49 virtual ~WindowManagerConnection() {}
50
51 private:
52 // Overridden from IWindowManager:
53 virtual void CloseWindow(Id node_id) OVERRIDE;
54
55 WindowManager* window_manager_;
56
57 DISALLOW_COPY_AND_ASSIGN(WindowManagerConnection);
58 };
59
60 class NavigatorHost : public InterfaceImpl<navigation::NavigatorHost> {
61 public:
NavigatorHost(WindowManager * window_manager)62 explicit NavigatorHost(WindowManager* window_manager)
63 : window_manager_(window_manager) {
64 }
~NavigatorHost()65 virtual ~NavigatorHost() {
66 }
67 private:
68 virtual void RequestNavigate(
69 uint32 source_node_id,
70 navigation::NavigationDetailsPtr nav_details) OVERRIDE;
71 WindowManager* window_manager_;
72 DISALLOW_COPY_AND_ASSIGN(NavigatorHost);
73 };
74
75 class WindowManager : public Application,
76 public ViewObserver,
77 public ViewManagerDelegate,
78 public InterfaceImpl<launcher::LauncherClient> {
79 public:
WindowManager()80 WindowManager() : launcher_ui_(NULL), view_manager_(NULL) {}
~WindowManager()81 virtual ~WindowManager() {}
82
CloseWindow(Id node_id)83 void CloseWindow(Id node_id) {
84 Node* node = view_manager_->GetNodeById(node_id);
85 DCHECK(node);
86 std::vector<Node*>::iterator iter =
87 std::find(windows_.begin(), windows_.end(), node);
88 DCHECK(iter != windows_.end());
89 windows_.erase(iter);
90 node->Destroy();
91 }
92
RequestNavigate(uint32 source_node_id,navigation::NavigationDetailsPtr nav_details)93 void RequestNavigate(
94 uint32 source_node_id,
95 navigation::NavigationDetailsPtr nav_details) {
96 if (!launcher_.get()) {
97 ConnectTo("mojo:mojo_launcher", &launcher_);
98 launcher_.set_client(this);
99 }
100 launcher_->Launch(nav_details->url);
101 }
102
103 private:
104 // Overridden from Application:
Initialize()105 virtual void Initialize() MOJO_OVERRIDE {
106 AddService<WindowManagerConnection>(this);
107 AddService<NavigatorHost>(this);
108 ViewManager::Create(this, this);
109 }
110
111 // Overridden from ViewObserver:
OnViewInputEvent(View * view,const EventPtr & event)112 virtual void OnViewInputEvent(View* view, const EventPtr& event) OVERRIDE {
113 if (event->action == ui::ET_MOUSE_RELEASED) {
114 std::string app_url;
115 if (event->flags & ui::EF_LEFT_MOUSE_BUTTON)
116 app_url = "mojo://mojo_embedded_app";
117 else if (event->flags & ui::EF_RIGHT_MOUSE_BUTTON)
118 app_url = "mojo://mojo_nesting_app";
119 if (app_url.empty())
120 return;
121
122 Node* node = view_manager_->GetNodeById(parent_node_id_);
123 navigation::NavigationDetailsPtr nav_details(
124 navigation::NavigationDetails::New());
125 size_t index = node->children().size() - 1;
126 nav_details->url = base::StringPrintf(
127 "%s/%x", app_url.c_str(), kColors[index % arraysize(kColors)]);
128 navigation::ResponseDetailsPtr response;
129 CreateWindow(app_url, nav_details.Pass(), response.Pass());
130 }
131 }
132
133 // Overridden from ViewManagerDelegate:
OnRootAdded(ViewManager * view_manager,Node * root)134 virtual void OnRootAdded(ViewManager* view_manager, Node* root) OVERRIDE {
135 DCHECK(!view_manager_);
136 view_manager_ = view_manager;
137
138 Node* node = Node::Create(view_manager);
139 view_manager->GetRoots().front()->AddChild(node);
140 node->SetBounds(gfx::Rect(800, 600));
141 parent_node_id_ = node->id();
142
143 View* view = View::Create(view_manager);
144 node->SetActiveView(view);
145 view->SetColor(SK_ColorBLUE);
146 view->AddObserver(this);
147
148 CreateLauncherUI();
149 }
150
151 // Overridden from LauncherClient:
OnLaunch(const mojo::String & requested_url,const mojo::String & handler_url,navigation::ResponseDetailsPtr response)152 virtual void OnLaunch(
153 const mojo::String& requested_url, const mojo::String& handler_url,
154 navigation::ResponseDetailsPtr response) OVERRIDE {
155 navigation::NavigationDetailsPtr nav_details(
156 navigation::NavigationDetails::New());
157 nav_details->url = requested_url;
158 CreateWindow(handler_url, nav_details.Pass(), response.Pass());
159 }
160
CreateLauncherUI()161 void CreateLauncherUI() {
162 navigation::NavigationDetailsPtr nav_details;
163 navigation::ResponseDetailsPtr response;
164 launcher_ui_ = CreateChild("mojo:mojo_browser", gfx::Rect(25, 25, 400, 25),
165 nav_details.Pass(), response.Pass());
166 }
167
CreateWindow(const std::string & handler_url,navigation::NavigationDetailsPtr nav_details,navigation::ResponseDetailsPtr response)168 void CreateWindow(const std::string& handler_url,
169 navigation::NavigationDetailsPtr nav_details,
170 navigation::ResponseDetailsPtr response) {
171 gfx::Rect bounds(25, 75, 400, 400);
172 if (!windows_.empty()) {
173 gfx::Point position = windows_.back()->bounds().origin();
174 position.Offset(35, 35);
175 bounds.set_origin(position);
176 }
177 windows_.push_back(CreateChild(handler_url, bounds, nav_details.Pass(),
178 response.Pass()));
179 }
180
CreateChild(const std::string & url,const gfx::Rect & bounds,navigation::NavigationDetailsPtr nav_details,navigation::ResponseDetailsPtr response)181 Node* CreateChild(const std::string& url,
182 const gfx::Rect& bounds,
183 navigation::NavigationDetailsPtr nav_details,
184 navigation::ResponseDetailsPtr response) {
185 Node* node = view_manager_->GetNodeById(parent_node_id_);
186 Node* embedded = Node::Create(view_manager_);
187 node->AddChild(embedded);
188 embedded->SetBounds(bounds);
189 embedded->Embed(url);
190
191 if (nav_details.get()) {
192 navigation::NavigatorPtr navigator;
193 ConnectTo(url, &navigator);
194 navigator->Navigate(embedded->id(), nav_details.Pass(), response.Pass());
195 }
196
197 return embedded;
198 }
199
200 launcher::LauncherPtr launcher_;
201 Node* launcher_ui_;
202 std::vector<Node*> windows_;
203 ViewManager* view_manager_;
204 Id parent_node_id_;
205
206 DISALLOW_COPY_AND_ASSIGN(WindowManager);
207 };
208
CloseWindow(Id node_id)209 void WindowManagerConnection::CloseWindow(Id node_id) {
210 window_manager_->CloseWindow(node_id);
211 }
212
RequestNavigate(uint32 source_node_id,navigation::NavigationDetailsPtr nav_details)213 void NavigatorHost::RequestNavigate(
214 uint32 source_node_id,
215 navigation::NavigationDetailsPtr nav_details) {
216 window_manager_->RequestNavigate(source_node_id, nav_details.Pass());
217 }
218
219 } // namespace examples
220
221 // static
Create()222 Application* Application::Create() {
223 return new examples::WindowManager;
224 }
225
226 } // namespace mojo
227