OLD | NEW |
1 // Copyright 2014 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "base/basictypes.h" | 5 #include "base/basictypes.h" |
6 #include "base/bind.h" | 6 #include "base/bind.h" |
7 #include "base/strings/stringprintf.h" | 7 #include "base/strings/stringprintf.h" |
8 #include "mojo/examples/window_manager/window_manager.mojom.h" | 8 #include "mojo/examples/window_manager/window_manager.mojom.h" |
9 #include "mojo/public/cpp/application/application.h" | 9 #include "mojo/public/cpp/application/application.h" |
10 #include "mojo/services/navigation/navigation.mojom.h" | 10 #include "mojo/services/navigation/navigation.mojom.h" |
11 #include "mojo/services/public/cpp/view_manager/node.h" | 11 #include "mojo/services/public/cpp/view_manager/node.h" |
12 #include "mojo/services/public/cpp/view_manager/view.h" | 12 #include "mojo/services/public/cpp/view_manager/view.h" |
13 #include "mojo/services/public/cpp/view_manager/view_manager.h" | 13 #include "mojo/services/public/cpp/view_manager/view_manager.h" |
14 #include "mojo/services/public/cpp/view_manager/view_manager_delegate.h" | 14 #include "mojo/services/public/cpp/view_manager/view_manager_delegate.h" |
15 #include "mojo/services/public/cpp/view_manager/view_observer.h" | 15 #include "mojo/services/public/cpp/view_manager/view_observer.h" |
| 16 #include "mojo/services/public/interfaces/launcher/launcher.mojom.h" |
16 #include "ui/events/event_constants.h" | 17 #include "ui/events/event_constants.h" |
17 | 18 |
18 #if defined CreateWindow | 19 #if defined CreateWindow |
19 #undef CreateWindow | 20 #undef CreateWindow |
20 #endif | 21 #endif |
21 | 22 |
22 using mojo::view_manager::Id; | 23 using mojo::view_manager::Id; |
23 using mojo::view_manager::Node; | 24 using mojo::view_manager::Node; |
24 using mojo::view_manager::NodeObserver; | 25 using mojo::view_manager::NodeObserver; |
25 using mojo::view_manager::View; | 26 using mojo::view_manager::View; |
26 using mojo::view_manager::ViewManager; | 27 using mojo::view_manager::ViewManager; |
27 using mojo::view_manager::ViewManagerDelegate; | 28 using mojo::view_manager::ViewManagerDelegate; |
28 using mojo::view_manager::ViewObserver; | 29 using mojo::view_manager::ViewObserver; |
29 | 30 |
30 namespace mojo { | 31 namespace mojo { |
31 namespace examples { | 32 namespace examples { |
32 | 33 |
33 class WindowManager; | 34 class WindowManager; |
34 | 35 |
35 namespace { | 36 namespace { |
36 | 37 |
37 const SkColor kColors[] = { SK_ColorYELLOW, | 38 const SkColor kColors[] = { SK_ColorYELLOW, |
38 SK_ColorRED, | 39 SK_ColorRED, |
39 SK_ColorGREEN, | 40 SK_ColorGREEN, |
40 SK_ColorMAGENTA }; | 41 SK_ColorMAGENTA }; |
41 | 42 |
42 const char kEmbeddedAppURL[] = "mojo:mojo_embedded_app"; | |
43 const char kNestingAppURL[] = "mojo:mojo_nesting_app"; | |
44 const char kMojoBrowserURL[] = "mojo:mojo_browser"; | |
45 | |
46 } // namespace | 43 } // namespace |
47 | 44 |
48 class WindowManagerConnection : public InterfaceImpl<IWindowManager> { | 45 class WindowManagerConnection : public InterfaceImpl<IWindowManager> { |
49 public: | 46 public: |
50 explicit WindowManagerConnection(WindowManager* window_manager) | 47 explicit WindowManagerConnection(WindowManager* window_manager) |
51 : window_manager_(window_manager) {} | 48 : window_manager_(window_manager) {} |
52 virtual ~WindowManagerConnection() {} | 49 virtual ~WindowManagerConnection() {} |
53 | 50 |
54 private: | 51 private: |
55 // Overridden from IWindowManager: | 52 // Overridden from IWindowManager: |
56 virtual void CloseWindow(Id node_id) OVERRIDE; | 53 virtual void CloseWindow(Id node_id) OVERRIDE; |
57 | 54 |
58 WindowManager* window_manager_; | 55 WindowManager* window_manager_; |
59 | 56 |
60 DISALLOW_COPY_AND_ASSIGN(WindowManagerConnection); | 57 DISALLOW_COPY_AND_ASSIGN(WindowManagerConnection); |
61 }; | 58 }; |
62 | 59 |
| 60 class NavigatorHost : public InterfaceImpl<navigation::NavigatorHost> { |
| 61 public: |
| 62 explicit NavigatorHost(WindowManager* window_manager) |
| 63 : window_manager_(window_manager) { |
| 64 } |
| 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 |
63 class WindowManager : public Application, | 75 class WindowManager : public Application, |
64 public ViewObserver, | 76 public ViewObserver, |
65 public ViewManagerDelegate { | 77 public ViewManagerDelegate, |
| 78 public InterfaceImpl<launcher::LauncherClient> { |
66 public: | 79 public: |
67 WindowManager() : view_manager_(NULL) {} | 80 WindowManager() : launcher_ui_(NULL), view_manager_(NULL) {} |
68 virtual ~WindowManager() {} | 81 virtual ~WindowManager() {} |
69 | 82 |
70 void CloseWindow(Id node_id) { | 83 void CloseWindow(Id node_id) { |
71 Node* node = view_manager_->GetNodeById(node_id); | 84 Node* node = view_manager_->GetNodeById(node_id); |
72 DCHECK(node); | 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); |
73 node->Destroy(); | 90 node->Destroy(); |
74 } | 91 } |
75 | 92 |
| 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 |
76 private: | 103 private: |
77 // Overridden from Application: | 104 // Overridden from Application: |
78 virtual void Initialize() MOJO_OVERRIDE { | 105 virtual void Initialize() MOJO_OVERRIDE { |
79 AddService<WindowManagerConnection>(this); | 106 AddService<WindowManagerConnection>(this); |
| 107 AddService<NavigatorHost>(this); |
80 ViewManager::Create(this, this); | 108 ViewManager::Create(this, this); |
81 } | 109 } |
82 | 110 |
83 // Overridden from ViewObserver: | 111 // Overridden from ViewObserver: |
84 virtual void OnViewInputEvent(View* view, const EventPtr& event) OVERRIDE { | 112 virtual void OnViewInputEvent(View* view, const EventPtr& event) OVERRIDE { |
85 if (event->action == ui::ET_MOUSE_RELEASED) { | 113 if (event->action == ui::ET_MOUSE_RELEASED) { |
| 114 std::string app_url; |
86 if (event->flags & ui::EF_LEFT_MOUSE_BUTTON) | 115 if (event->flags & ui::EF_LEFT_MOUSE_BUTTON) |
87 CreateWindow(kEmbeddedAppURL); | 116 app_url = "mojo:mojo_embedded_app"; |
88 else if (event->flags & ui::EF_RIGHT_MOUSE_BUTTON) | 117 else if (event->flags & ui::EF_RIGHT_MOUSE_BUTTON) |
89 CreateWindow(kNestingAppURL); | 118 app_url = "mojo:mojo_nesting_app"; |
| 119 DCHECK(!app_url.empty()); |
| 120 |
| 121 Node* node = view_manager_->GetNodeById(parent_node_id_); |
| 122 navigation::NavigationDetailsPtr nav_details( |
| 123 navigation::NavigationDetails::New()); |
| 124 size_t index = node->children().size() - 1; |
| 125 nav_details->url = base::StringPrintf( |
| 126 "%s/%x", app_url.c_str(), kColors[index % arraysize(kColors)]); |
| 127 navigation::ResponseDetailsPtr response; |
| 128 CreateWindow(app_url, nav_details.Pass(), response.Pass()); |
90 } | 129 } |
91 } | 130 } |
92 | 131 |
93 // Overridden from ViewManagerDelegate: | 132 // Overridden from ViewManagerDelegate: |
94 virtual void OnRootAdded(ViewManager* view_manager, Node* root) OVERRIDE { | 133 virtual void OnRootAdded(ViewManager* view_manager, Node* root) OVERRIDE { |
95 DCHECK(!view_manager_); | 134 DCHECK(!view_manager_); |
96 view_manager_ = view_manager; | 135 view_manager_ = view_manager; |
97 | 136 |
98 Node* node = Node::Create(view_manager); | 137 Node* node = Node::Create(view_manager); |
99 view_manager->GetRoots().front()->AddChild(node); | 138 view_manager->GetRoots().front()->AddChild(node); |
100 node->SetBounds(gfx::Rect(800, 600)); | 139 node->SetBounds(gfx::Rect(800, 600)); |
101 parent_node_id_ = node->id(); | 140 parent_node_id_ = node->id(); |
102 | 141 |
103 View* view = View::Create(view_manager); | 142 View* view = View::Create(view_manager); |
104 node->SetActiveView(view); | 143 node->SetActiveView(view); |
105 view->SetColor(SK_ColorBLUE); | 144 view->SetColor(SK_ColorBLUE); |
106 view->AddObserver(this); | 145 view->AddObserver(this); |
107 | 146 |
108 CreateWindow(kMojoBrowserURL); | 147 CreateLauncherUI(); |
109 } | 148 } |
110 | 149 |
111 void CreateWindow(const std::string& url) { | 150 // Overridden from LauncherClient: |
112 Node* node = view_manager_->GetNodeById(parent_node_id_); | 151 virtual void OnLaunch( |
| 152 const mojo::String& handler_url, mojo::URLResponsePtr response, |
| 153 mojo::ScopedDataPipeConsumerHandle response_body_stream) OVERRIDE { |
| 154 navigation::NavigationDetailsPtr nav_details( |
| 155 navigation::NavigationDetails::New()); |
| 156 nav_details->url = response->url; |
| 157 navigation::ResponseDetailsPtr response_details( |
| 158 navigation::ResponseDetails::New()); |
| 159 response_details->response = response.Pass(); |
| 160 response_details->response_body_stream = response_body_stream.Pass(); |
| 161 CreateWindow(handler_url, nav_details.Pass(), response_details.Pass()); |
| 162 } |
113 | 163 |
114 gfx::Rect bounds(node->bounds().size()); | 164 void CreateLauncherUI() { |
115 bounds.Inset(25, 25); | 165 navigation::NavigationDetailsPtr nav_details; |
116 if (!node->children().empty()) { | 166 navigation::ResponseDetailsPtr response; |
117 gfx::Point position = node->children().back()->bounds().origin(); | 167 launcher_ui_ = CreateChild("mojo:mojo_browser", gfx::Rect(25, 25, 400, 25), |
118 position.Offset(25, 25); | 168 nav_details.Pass(), response.Pass()); |
| 169 } |
| 170 |
| 171 void CreateWindow(const std::string& handler_url, |
| 172 navigation::NavigationDetailsPtr nav_details, |
| 173 navigation::ResponseDetailsPtr response) { |
| 174 gfx::Rect bounds(25, 75, 400, 400); |
| 175 if (!windows_.empty()) { |
| 176 gfx::Point position = windows_.back()->bounds().origin(); |
| 177 position.Offset(35, 35); |
119 bounds.set_origin(position); | 178 bounds.set_origin(position); |
120 } | 179 } |
| 180 windows_.push_back(CreateChild(handler_url, bounds, nav_details.Pass(), |
| 181 response.Pass())); |
| 182 } |
121 | 183 |
| 184 Node* CreateChild(const std::string& url, |
| 185 const gfx::Rect& bounds, |
| 186 navigation::NavigationDetailsPtr nav_details, |
| 187 navigation::ResponseDetailsPtr response) { |
| 188 Node* node = view_manager_->GetNodeById(parent_node_id_); |
122 Node* embedded = Node::Create(view_manager_); | 189 Node* embedded = Node::Create(view_manager_); |
123 node->AddChild(embedded); | 190 node->AddChild(embedded); |
124 embedded->SetBounds(bounds); | 191 embedded->SetBounds(bounds); |
125 embedded->Embed(url); | 192 embedded->Embed(url); |
126 | 193 |
127 // TODO(aa): Is there a way to ask for an interface and test whether it | 194 if (nav_details.get()) { |
128 // succeeded? That would be nicer than hard-coding the URLs that are known | |
129 // to support navigation. | |
130 if (url == kEmbeddedAppURL || url == kNestingAppURL) { | |
131 // TODO(aa): This means that there can only ever be one instance of every | |
132 // app, which seems wrong. Instead, perhaps embedder should get back a | |
133 // service provider that allows it to talk to embeddee. | |
134 navigation::NavigatorPtr navigator; | 195 navigation::NavigatorPtr navigator; |
135 ConnectTo(url, &navigator); | 196 ConnectTo(url, &navigator); |
136 navigation::NavigationDetailsPtr details( | 197 navigator->Navigate(embedded->id(), nav_details.Pass(), response.Pass()); |
137 navigation::NavigationDetails::New()); | 198 } |
138 size_t index = node->children().size() - 1; | |
139 details->url = base::StringPrintf( | |
140 "%s/%x", kEmbeddedAppURL, kColors[index % arraysize(kColors)]); | |
141 | 199 |
142 // TODO(beng): remove once nullable parameters land. | 200 return embedded; |
143 navigation::ResponseDetailsPtr response_details( | |
144 navigation::ResponseDetails::New()); | |
145 navigator->Navigate(embedded->id(), | |
146 details.Pass(), | |
147 response_details.Pass()); | |
148 } | |
149 } | 201 } |
150 | 202 |
| 203 launcher::LauncherPtr launcher_; |
| 204 Node* launcher_ui_; |
| 205 std::vector<Node*> windows_; |
151 ViewManager* view_manager_; | 206 ViewManager* view_manager_; |
152 Id parent_node_id_; | 207 Id parent_node_id_; |
153 | 208 |
154 DISALLOW_COPY_AND_ASSIGN(WindowManager); | 209 DISALLOW_COPY_AND_ASSIGN(WindowManager); |
155 }; | 210 }; |
156 | 211 |
157 void WindowManagerConnection::CloseWindow(Id node_id) { | 212 void WindowManagerConnection::CloseWindow(Id node_id) { |
158 window_manager_->CloseWindow(node_id); | 213 window_manager_->CloseWindow(node_id); |
159 } | 214 } |
160 | 215 |
| 216 void NavigatorHost::RequestNavigate( |
| 217 uint32 source_node_id, |
| 218 navigation::NavigationDetailsPtr nav_details) { |
| 219 window_manager_->RequestNavigate(source_node_id, nav_details.Pass()); |
| 220 } |
| 221 |
161 } // namespace examples | 222 } // namespace examples |
162 | 223 |
163 // static | 224 // static |
164 Application* Application::Create() { | 225 Application* Application::Create() { |
165 return new examples::WindowManager; | 226 return new examples::WindowManager; |
166 } | 227 } |
167 | 228 |
168 } // namespace mojo | 229 } // namespace mojo |
OLD | NEW |