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"; |
90 else if (event->flags & ui::EF_MIDDLE_MOUSE_BUTTON) | 119 DCHECK(!app_url.empty()); |
91 CreateWindow(kMojoBrowserURL); | 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 CreateWindow(app_url, nav_details.Pass()); |
92 } | 128 } |
93 } | 129 } |
94 | 130 |
95 // Overridden from ViewManagerDelegate: | 131 // Overridden from ViewManagerDelegate: |
96 virtual void OnRootAdded(ViewManager* view_manager, Node* root) OVERRIDE { | 132 virtual void OnRootAdded(ViewManager* view_manager, Node* root) OVERRIDE { |
97 DCHECK(!view_manager_); | 133 DCHECK(!view_manager_); |
98 view_manager_ = view_manager; | 134 view_manager_ = view_manager; |
99 | 135 |
100 Node* node = Node::Create(view_manager); | 136 Node* node = Node::Create(view_manager); |
101 view_manager->GetRoots().front()->AddChild(node); | 137 view_manager->GetRoots().front()->AddChild(node); |
102 node->SetBounds(gfx::Rect(800, 600)); | 138 node->SetBounds(gfx::Rect(800, 600)); |
103 parent_node_id_ = node->id(); | 139 parent_node_id_ = node->id(); |
104 | 140 |
105 View* view = View::Create(view_manager); | 141 View* view = View::Create(view_manager); |
106 node->SetActiveView(view); | 142 node->SetActiveView(view); |
107 view->SetColor(SK_ColorBLUE); | 143 view->SetColor(SK_ColorBLUE); |
108 view->AddObserver(this); | 144 view->AddObserver(this); |
| 145 |
| 146 CreateLauncherUI(); |
109 } | 147 } |
110 | 148 |
111 void CreateWindow(const std::string& url) { | 149 // Overridden from LauncherClient: |
112 Node* node = view_manager_->GetNodeById(parent_node_id_); | 150 virtual void OnLaunch( |
| 151 const mojo::String& handler_url, |
| 152 URLResponsePtr response, |
| 153 ScopedDataPipeConsumerHandle response_body_stream) OVERRIDE { |
| 154 navigation::NavigationDetailsPtr nav_details( |
| 155 navigation::NavigationDetails::New()); |
| 156 nav_details->url = response->url; |
| 157 nav_details->response = response.Pass(); |
| 158 nav_details->response_body_stream = response_body_stream.Pass(); |
| 159 CreateWindow(handler_url, nav_details.Pass()); |
| 160 } |
113 | 161 |
114 gfx::Rect bounds(50, 50, 400, 400); | 162 void CreateLauncherUI() { |
115 if (!node->children().empty()) { | 163 navigation::NavigationDetailsPtr nav_details; |
116 gfx::Point position = node->children().back()->bounds().origin(); | 164 launcher_ui_ = CreateChild("mojo:mojo_browser", gfx::Rect(25, 25, 400, 25), |
117 position.Offset(50, 50); | 165 nav_details.Pass()); |
| 166 } |
| 167 |
| 168 void CreateWindow(const std::string& handler_url, |
| 169 navigation::NavigationDetailsPtr nav_details) { |
| 170 gfx::Rect bounds(25, 75, 400, 400); |
| 171 if (!windows_.empty()) { |
| 172 gfx::Point position = windows_.back()->bounds().origin(); |
| 173 position.Offset(35, 35); |
118 bounds.set_origin(position); | 174 bounds.set_origin(position); |
119 } | 175 } |
| 176 windows_.push_back(CreateChild(handler_url, bounds, nav_details.Pass())); |
| 177 } |
120 | 178 |
| 179 Node* CreateChild(const std::string& url, |
| 180 const gfx::Rect& bounds, |
| 181 navigation::NavigationDetailsPtr nav_details) { |
| 182 Node* node = view_manager_->GetNodeById(parent_node_id_); |
121 Node* embedded = Node::Create(view_manager_); | 183 Node* embedded = Node::Create(view_manager_); |
122 node->AddChild(embedded); | 184 node->AddChild(embedded); |
123 embedded->SetBounds(bounds); | 185 embedded->SetBounds(bounds); |
124 embedded->Embed(url); | 186 embedded->Embed(url); |
125 | 187 |
126 // TODO(aa): Is there a way to ask for an interface and test whether it | 188 if (nav_details.get()) { |
127 // succeeded? That would be nicer than hard-coding the URLs that are known | |
128 // to support navigation. | |
129 if (url == kEmbeddedAppURL || url == kNestingAppURL) { | |
130 // TODO(aa): This means that there can only ever be one instance of every | |
131 // app, which seems wrong. Instead, perhaps embedder should get back a | |
132 // service provider that allows it to talk to embeddee. | |
133 navigation::NavigatorPtr navigator; | 189 navigation::NavigatorPtr navigator; |
134 ConnectTo(url, &navigator); | 190 ConnectTo(url, &navigator); |
135 navigation::NavigationDetailsPtr details( | 191 navigator->Navigate(embedded->id(), nav_details.Pass()); |
136 navigation::NavigationDetails::New()); | |
137 size_t index = node->children().size() - 1; | |
138 details->url = base::StringPrintf( | |
139 "%s/%x", kEmbeddedAppURL, kColors[index % arraysize(kColors)]); | |
140 navigator->Navigate(embedded->id(), details.Pass()); | |
141 } | 192 } |
| 193 |
| 194 return embedded; |
142 } | 195 } |
143 | 196 |
| 197 launcher::LauncherPtr launcher_; |
| 198 Node* launcher_ui_; |
| 199 std::vector<Node*> windows_; |
144 ViewManager* view_manager_; | 200 ViewManager* view_manager_; |
145 Id parent_node_id_; | 201 Id parent_node_id_; |
146 | 202 |
147 DISALLOW_COPY_AND_ASSIGN(WindowManager); | 203 DISALLOW_COPY_AND_ASSIGN(WindowManager); |
148 }; | 204 }; |
149 | 205 |
150 void WindowManagerConnection::CloseWindow(Id node_id) { | 206 void WindowManagerConnection::CloseWindow(Id node_id) { |
151 window_manager_->CloseWindow(node_id); | 207 window_manager_->CloseWindow(node_id); |
152 } | 208 } |
153 | 209 |
| 210 void NavigatorHost::RequestNavigate( |
| 211 uint32 source_node_id, |
| 212 navigation::NavigationDetailsPtr nav_details) { |
| 213 window_manager_->RequestNavigate(source_node_id, nav_details.Pass()); |
| 214 } |
| 215 |
154 } // namespace examples | 216 } // namespace examples |
155 | 217 |
156 // static | 218 // static |
157 Application* Application::Create() { | 219 Application* Application::Create() { |
158 return new examples::WindowManager; | 220 return new examples::WindowManager; |
159 } | 221 } |
160 | 222 |
161 } // namespace mojo | 223 } // namespace mojo |
OLD | NEW |