| 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 |