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: 47 explicit WindowManagerConnection(WindowManager* window_manager) 48 : window_manager_(window_manager) {} 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: 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 75 class WindowManager : public Application, 76 public ViewObserver, 77 public ViewManagerDelegate, 78 public InterfaceImpl<launcher::LauncherClient> { 79 public: 80 WindowManager() : launcher_ui_(NULL), view_manager_(NULL) {} 81 virtual ~WindowManager() {} 82 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 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: 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: 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: 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: 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 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 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 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 209 void WindowManagerConnection::CloseWindow(Id node_id) { 210 window_manager_->CloseWindow(node_id); 211 } 212 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 222 Application* Application::Create() { 223 return new examples::WindowManager; 224 } 225 226 } // namespace mojo 227