Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(760)

Side by Side Diff: examples/window_manager/window_manager.cc

Issue 1397563003: Remove wm_flow, browser, nesting_app examples (Closed) Base URL: git@github.com:domokit/mojo.git@master
Patch Set: Created 5 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
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/bind.h"
6 #include "base/macros.h"
7 #include "examples/window_manager/debug_panel_host.mojom.h"
8 #include "examples/window_manager/window_manager.mojom.h"
9 #include "mojo/application/application_runner_chromium.h"
10 #include "mojo/common/binding_set.h"
11 #include "mojo/converters/geometry/geometry_type_converters.h"
12 #include "mojo/converters/input_events/input_events_type_converters.h"
13 #include "mojo/public/c/system/main.h"
14 #include "mojo/public/cpp/application/application_connection.h"
15 #include "mojo/public/cpp/application/application_delegate.h"
16 #include "mojo/public/cpp/application/application_impl.h"
17 #include "mojo/public/cpp/application/service_provider_impl.h"
18 #include "mojo/public/cpp/bindings/strong_binding.h"
19 #include "mojo/services/input_events/interfaces/input_events.mojom.h"
20 #include "mojo/services/navigation/interfaces/navigation.mojom.h"
21 #include "mojo/services/view_manager/cpp/view.h"
22 #include "mojo/services/view_manager/cpp/view_manager.h"
23 #include "mojo/services/view_manager/cpp/view_manager_delegate.h"
24 #include "mojo/services/view_manager/cpp/view_observer.h"
25 #include "services/window_manager/basic_focus_rules.h"
26 #include "services/window_manager/view_target.h"
27 #include "services/window_manager/window_manager_app.h"
28 #include "services/window_manager/window_manager_delegate.h"
29 #include "services/window_manager/window_manager_root.h"
30 #include "ui/events/event.h"
31 #include "ui/events/event_constants.h"
32 #include "url/gurl.h"
33
34 #if defined CreateWindow
35 #undef CreateWindow
36 #endif
37
38 namespace mojo {
39 namespace examples {
40
41 class WindowManagerController;
42
43 namespace {
44
45 const int kBorderInset = 25;
46 const int kControlPanelWidth = 200;
47 const int kTextfieldHeight = 39;
48
49 } // namespace
50
51 class WindowManagerConnection : public ::examples::IWindowManager {
52 public:
53 WindowManagerConnection(WindowManagerController* window_manager,
54 InterfaceRequest<::examples::IWindowManager> request)
55 : window_manager_(window_manager), binding_(this, request.Pass()) {}
56 ~WindowManagerConnection() override {}
57
58 private:
59 // Overridden from ::examples::IWindowManager:
60 void CloseWindow(Id view_id) override;
61
62 WindowManagerController* window_manager_;
63 StrongBinding<::examples::IWindowManager> binding_;
64
65 DISALLOW_COPY_AND_ASSIGN(WindowManagerConnection);
66 };
67
68 class NavigatorHostImpl : public NavigatorHost {
69 public:
70 NavigatorHostImpl(WindowManagerController* window_manager, Id view_id)
71 : window_manager_(window_manager),
72 view_id_(view_id),
73 current_index_(-1) {}
74 ~NavigatorHostImpl() override {}
75
76 void Bind(InterfaceRequest<NavigatorHost> request) {
77 bindings_.AddBinding(this, request.Pass());
78 }
79
80 void RecordNavigation(const std::string& url);
81
82 private:
83 void DidNavigateLocally(const mojo::String& url) override;
84 void RequestNavigate(Target target, URLRequestPtr request) override;
85 void RequestNavigateHistory(int32_t delta) override;
86
87 WindowManagerController* window_manager_;
88 Id view_id_;
89 std::vector<std::string> history_;
90 int32_t current_index_;
91
92 BindingSet<NavigatorHost> bindings_;
93
94 DISALLOW_COPY_AND_ASSIGN(NavigatorHostImpl);
95 };
96
97 class RootLayoutManager : public ViewObserver {
98 public:
99 RootLayoutManager(ViewManager* view_manager,
100 View* root,
101 Id content_view_id,
102 Id launcher_ui_view_id,
103 Id control_panel_view_id)
104 : root_(root),
105 view_manager_(view_manager),
106 content_view_id_(content_view_id),
107 launcher_ui_view_id_(launcher_ui_view_id),
108 control_panel_view_id_(control_panel_view_id) {}
109 ~RootLayoutManager() override {
110 if (root_)
111 root_->RemoveObserver(this);
112 }
113
114 private:
115 // Overridden from ViewObserver:
116 void OnViewBoundsChanged(View* view,
117 const Rect& old_bounds,
118 const Rect& new_bounds) override {
119 DCHECK_EQ(view, root_);
120
121 View* content_view = view_manager_->GetViewById(content_view_id_);
122 content_view->SetBounds(new_bounds);
123
124 int delta_width = new_bounds.width - old_bounds.width;
125 int delta_height = new_bounds.height - old_bounds.height;
126
127 View* launcher_ui_view = view_manager_->GetViewById(launcher_ui_view_id_);
128 Rect launcher_ui_bounds(launcher_ui_view->bounds());
129 launcher_ui_bounds.width += delta_width;
130 launcher_ui_view->SetBounds(launcher_ui_bounds);
131
132 View* control_panel_view =
133 view_manager_->GetViewById(control_panel_view_id_);
134 Rect control_panel_bounds(control_panel_view->bounds());
135 control_panel_bounds.x += delta_width;
136 control_panel_view->SetBounds(control_panel_bounds);
137
138 const View::Children& content_views = content_view->children();
139 View::Children::const_iterator iter = content_views.begin();
140 for (; iter != content_views.end(); ++iter) {
141 View* view = *iter;
142 if (view->id() == control_panel_view->id() ||
143 view->id() == launcher_ui_view->id())
144 continue;
145 Rect view_bounds(view->bounds());
146 view_bounds.width += delta_width;
147 view_bounds.height += delta_height;
148 view->SetBounds(view_bounds);
149 }
150 }
151 void OnViewDestroyed(View* view) override {
152 DCHECK_EQ(view, root_);
153 root_->RemoveObserver(this);
154 root_ = NULL;
155 }
156
157 View* root_;
158 ViewManager* view_manager_;
159 const Id content_view_id_;
160 const Id launcher_ui_view_id_;
161 const Id control_panel_view_id_;
162
163 DISALLOW_COPY_AND_ASSIGN(RootLayoutManager);
164 };
165
166 class Window : public InterfaceFactory<NavigatorHost> {
167 public:
168 Window(WindowManagerController* window_manager, View* view)
169 : window_manager_(window_manager),
170 view_(view),
171 navigator_host_(window_manager_, view_->id()) {
172 exposed_services_impl_.AddService<NavigatorHost>(this);
173 }
174
175 ~Window() override {}
176
177 View* view() const { return view_; }
178
179 NavigatorHost* navigator_host() { return &navigator_host_; }
180
181 void Embed(const std::string& url) {
182 // TODO: Support embedding multiple times?
183 ServiceProviderPtr exposed_services;
184 exposed_services_impl_.Bind(GetProxy(&exposed_services));
185 view_->Embed(url, nullptr, exposed_services.Pass());
186 navigator_host_.RecordNavigation(url);
187 }
188
189 private:
190 // InterfaceFactory<NavigatorHost>
191 void Create(ApplicationConnection* connection,
192 InterfaceRequest<NavigatorHost> request) override {
193 navigator_host_.Bind(request.Pass());
194 }
195
196 WindowManagerController* window_manager_;
197 View* view_;
198 ServiceProviderImpl exposed_services_impl_;
199 NavigatorHostImpl navigator_host_;
200 };
201
202 class WindowManagerController
203 : public examples::DebugPanelHost,
204 public window_manager::WindowManagerController,
205 public ui::EventHandler,
206 public ui::AcceleratorTarget,
207 public mojo::InterfaceFactory<examples::DebugPanelHost>,
208 public InterfaceFactory<::examples::IWindowManager> {
209 public:
210 WindowManagerController(Shell* shell,
211 ApplicationImpl* app,
212 ApplicationConnection* connection,
213 window_manager::WindowManagerRoot* wm_root)
214 : shell_(shell),
215 launcher_ui_(NULL),
216 view_manager_(NULL),
217 window_manager_root_(wm_root),
218 navigation_target_(Target::DEFAULT),
219 app_(app),
220 binding_(this) {
221 connection->AddService<::examples::IWindowManager>(this);
222 }
223
224 ~WindowManagerController() override {
225 // host() may be destroyed by the time we get here.
226 // TODO: figure out a way to always cleanly remove handler.
227
228 // TODO(erg): In the aura version, we removed ourselves from the
229 // PreTargetHandler list here. We may need to do something analogous when
230 // we get event handling without aura working.
231 }
232
233 void CloseWindow(Id view_id) {
234 WindowVector::iterator iter = GetWindowByViewId(view_id);
235 DCHECK(iter != windows_.end());
236 Window* window = *iter;
237 windows_.erase(iter);
238 window->view()->Destroy();
239 }
240
241 void DidNavigateLocally(uint32 source_view_id, const mojo::String& url) {
242 LOG(ERROR) << "DidNavigateLocally: source_view_id: " << source_view_id
243 << " url: " << url.To<std::string>();
244 }
245
246 void RequestNavigate(uint32 source_view_id,
247 Target target,
248 const mojo::String& url) {
249 OnLaunch(source_view_id, target, url);
250 }
251
252 // Overridden from mojo::DebugPanelHost:
253 void CloseTopWindow() override {
254 if (!windows_.empty())
255 CloseWindow(windows_.back()->view()->id());
256 }
257
258 void NavigateTo(const String& url) override {
259 OnLaunch(control_panel_id_, Target::NEW_NODE, url);
260 }
261
262 void SetNavigationTarget(Target t) override { navigation_target_ = t; }
263
264 // mojo::InterfaceFactory<examples::DebugPanelHost> implementation.
265 void Create(
266 mojo::ApplicationConnection* connection,
267 mojo::InterfaceRequest<examples::DebugPanelHost> request) override {
268 binding_.Bind(request.Pass());
269 }
270
271 // mojo::InterfaceFactory<::examples::IWindowManager> implementation.
272 void Create(
273 mojo::ApplicationConnection* connection,
274 mojo::InterfaceRequest<::examples::IWindowManager> request) override {
275 new WindowManagerConnection(this, request.Pass());
276 }
277
278 private:
279 typedef std::vector<Window*> WindowVector;
280
281 // Overridden from ViewManagerDelegate:
282 void OnEmbed(View* root,
283 InterfaceRequest<ServiceProvider> services,
284 ServiceProviderPtr exposed_services) override {
285 DCHECK(!view_manager_);
286 view_manager_ = root->view_manager();
287
288 View* view = view_manager_->CreateView();
289 root->AddChild(view);
290 Rect rect;
291 rect.width = root->bounds().width;
292 rect.height = root->bounds().height;
293 view->SetBounds(rect);
294 view->SetVisible(true);
295 content_view_id_ = view->id();
296
297 Id launcher_ui_id = CreateLauncherUI();
298 control_panel_id_ = CreateControlPanel(view);
299
300 root_layout_manager_.reset(
301 new RootLayoutManager(view_manager_, root, content_view_id_,
302 launcher_ui_id, control_panel_id_));
303 root->AddObserver(root_layout_manager_.get());
304
305 // TODO(erg): In the aura version, we explicitly added ourselves as a
306 // PreTargetHandler to the window() here. We probably have to do something
307 // analogous here.
308
309 window_manager_root_->InitFocus(
310 make_scoped_ptr(new window_manager::BasicFocusRules(root)));
311 window_manager_root_->accelerator_manager()->Register(
312 ui::Accelerator(ui::VKEY_BROWSER_BACK, 0),
313 ui::AcceleratorManager::kNormalPriority, this);
314 }
315 void OnViewManagerDisconnected(ViewManager* view_manager) override {
316 DCHECK_EQ(view_manager_, view_manager);
317 view_manager_ = NULL;
318 base::MessageLoop::current()->Quit();
319 }
320
321 // Overridden from WindowManagerDelegate:
322 void Embed(const String& url,
323 InterfaceRequest<ServiceProvider> services,
324 ServiceProviderPtr exposed_services) override {
325 const Id kInvalidSourceViewId = 0;
326 OnLaunch(kInvalidSourceViewId, Target::DEFAULT, url);
327 }
328
329 // Overridden from ui::EventHandler:
330 void OnEvent(ui::Event* event) override {
331 View* view =
332 static_cast<window_manager::ViewTarget*>(event->target())->view();
333 if (event->type() == ui::ET_MOUSE_PRESSED)
334 view->SetFocus();
335 }
336
337 // Overriden from ui::AcceleratorTarget:
338 bool AcceleratorPressed(const ui::Accelerator& accelerator,
339 mojo::View* view) override {
340 if (accelerator.key_code() != ui::VKEY_BROWSER_BACK)
341 return false;
342
343 WindowVector::iterator iter = GetWindowByViewId(view->id());
344 DCHECK(iter != windows_.end());
345 Window* window = *iter;
346 window->navigator_host()->RequestNavigateHistory(-1);
347 return true;
348 }
349
350 // Overriden from ui::AcceleratorTarget:
351 bool CanHandleAccelerators() const override { return true; }
352
353 void OnLaunch(uint32 source_view_id,
354 Target requested_target,
355 const mojo::String& url) {
356 Target target = navigation_target_;
357 if (target == Target::DEFAULT) {
358 if (requested_target != Target::DEFAULT) {
359 target = requested_target;
360 } else {
361 // TODO(aa): Should be Target::NEW_NODE if source origin and dest origin
362 // are different?
363 target = Target::SOURCE_NODE;
364 }
365 }
366
367 Window* dest_view = NULL;
368 if (target == Target::SOURCE_NODE) {
369 WindowVector::iterator source_view = GetWindowByViewId(source_view_id);
370 bool app_initiated = source_view != windows_.end();
371 if (app_initiated)
372 dest_view = *source_view;
373 else if (!windows_.empty())
374 dest_view = windows_.back();
375 }
376
377 if (!dest_view) {
378 dest_view = CreateWindow();
379 windows_.push_back(dest_view);
380 }
381
382 dest_view->Embed(url);
383 }
384
385 // TODO(beng): proper layout manager!!
386 Id CreateLauncherUI() {
387 View* view = view_manager_->GetViewById(content_view_id_);
388 Rect bounds = view->bounds();
389 bounds.x += kBorderInset;
390 bounds.y += kBorderInset;
391 bounds.width -= 2 * kBorderInset;
392 bounds.height = kTextfieldHeight;
393 launcher_ui_ = CreateWindow(bounds);
394 launcher_ui_->Embed("mojo:browser");
395 return launcher_ui_->view()->id();
396 }
397
398 Window* CreateWindow() {
399 View* view = view_manager_->GetViewById(content_view_id_);
400 Rect bounds;
401 bounds.x = kBorderInset;
402 bounds.y = 2 * kBorderInset + kTextfieldHeight;
403 bounds.width = view->bounds().width - 3 * kBorderInset - kControlPanelWidth;
404 bounds.height =
405 view->bounds().height - (3 * kBorderInset + kTextfieldHeight);
406 if (!windows_.empty()) {
407 bounds.x = windows_.back()->view()->bounds().x + 35;
408 bounds.y = windows_.back()->view()->bounds().y + 35;
409 }
410 return CreateWindow(bounds);
411 }
412
413 Window* CreateWindow(const Rect& bounds) {
414 View* content = view_manager_->GetViewById(content_view_id_);
415 View* view = view_manager_->CreateView();
416 content->AddChild(view);
417 view->SetBounds(bounds);
418 view->SetVisible(true);
419 view->SetFocus();
420 return new Window(this, view);
421 }
422
423 Id CreateControlPanel(View* root) {
424 View* view = view_manager_->CreateView();
425 root->AddChild(view);
426
427 Rect bounds;
428 bounds.x = root->bounds().width - kControlPanelWidth - kBorderInset;
429 bounds.y = kBorderInset * 2 + kTextfieldHeight;
430 bounds.width = kControlPanelWidth;
431 bounds.height = root->bounds().height - kBorderInset * 3 - kTextfieldHeight;
432 view->SetBounds(bounds);
433 view->SetVisible(true);
434
435 ServiceProviderPtr exposed_services;
436 control_panel_exposed_services_impl_.Bind(GetProxy(&exposed_services));
437 control_panel_exposed_services_impl_.AddService<::examples::IWindowManager>(
438 this);
439
440 GURL frame_url = url_.Resolve("/examples/window_manager/debug_panel.sky");
441 view->Embed(frame_url.spec(), nullptr, exposed_services.Pass());
442
443 return view->id();
444 }
445
446 WindowVector::iterator GetWindowByViewId(Id view_id) {
447 for (std::vector<Window*>::iterator iter = windows_.begin();
448 iter != windows_.end(); ++iter) {
449 if ((*iter)->view()->id() == view_id) {
450 return iter;
451 }
452 }
453 return windows_.end();
454 }
455
456 Shell* shell_;
457
458 Window* launcher_ui_;
459 WindowVector windows_;
460 ViewManager* view_manager_;
461 scoped_ptr<RootLayoutManager> root_layout_manager_;
462 ServiceProviderImpl control_panel_exposed_services_impl_;
463
464 window_manager::WindowManagerRoot* window_manager_root_;
465
466 // Id of the view most content is added to.
467 Id content_view_id_;
468
469 // Id of the debug panel.
470 Id control_panel_id_;
471
472 GURL url_;
473 Target navigation_target_;
474
475 ApplicationImpl* app_;
476
477 mojo::Binding<examples::DebugPanelHost> binding_;
478
479 DISALLOW_COPY_AND_ASSIGN(WindowManagerController);
480 };
481
482 class WindowManager : public ApplicationDelegate,
483 public window_manager::WindowManagerControllerFactory {
484 public:
485 WindowManager()
486 : window_manager_app_(new window_manager::WindowManagerApp(this)) {}
487
488 scoped_ptr<window_manager::WindowManagerController>
489 CreateWindowManagerController(
490 ApplicationConnection* connection,
491 window_manager::WindowManagerRoot* wm_root) override {
492 return scoped_ptr<WindowManagerController>(
493 new WindowManagerController(shell_, app_, connection, wm_root));
494 }
495
496 private:
497 // Overridden from ApplicationDelegate:
498 void Initialize(ApplicationImpl* app) override {
499 window_manager_app_.reset(new window_manager::WindowManagerApp(this));
500 shell_ = app->shell();
501 app_ = app;
502 // FIXME: Mojo applications don't know their URLs yet:
503 // https://docs.google.com/a/chromium.org/document/d/1AQ2y6ekzvbdaMF5WrUQmne yXJnke-MnYYL4Gz1AKDos
504 url_ = GURL(app->args()[1]);
505 window_manager_app_->Initialize(app);
506 }
507
508 bool ConfigureIncomingConnection(ApplicationConnection* connection) override {
509 window_manager_app_->ConfigureIncomingConnection(connection);
510 return true;
511 }
512
513 ApplicationImpl* app_;
514 Shell* shell_;
515 GURL url_;
516
517 scoped_ptr<window_manager::WindowManagerApp> window_manager_app_;
518 DISALLOW_COPY_AND_ASSIGN(WindowManager);
519 };
520
521 void WindowManagerConnection::CloseWindow(Id view_id) {
522 window_manager_->CloseWindow(view_id);
523 }
524
525 void NavigatorHostImpl::DidNavigateLocally(const mojo::String& url) {
526 window_manager_->DidNavigateLocally(view_id_, url);
527 RecordNavigation(url);
528 }
529
530 void NavigatorHostImpl::RequestNavigate(Target target, URLRequestPtr request) {
531 window_manager_->RequestNavigate(view_id_, target, request->url);
532 }
533
534 void NavigatorHostImpl::RequestNavigateHistory(int32_t delta) {
535 if (history_.empty())
536 return;
537 current_index_ =
538 std::max(0, std::min(current_index_ + delta,
539 static_cast<int32_t>(history_.size()) - 1));
540 window_manager_->RequestNavigate(view_id_, Target::SOURCE_NODE,
541 history_[current_index_]);
542 }
543
544 void NavigatorHostImpl::RecordNavigation(const std::string& url) {
545 if (current_index_ >= 0 && history_[current_index_] == url) {
546 // This is a navigation to the current entry, ignore.
547 return;
548 }
549 history_.erase(history_.begin() + (current_index_ + 1), history_.end());
550 history_.push_back(url);
551 ++current_index_;
552 }
553
554 } // namespace examples
555 } // namespace mojo
556
557 MojoResult MojoMain(MojoHandle application_request) {
558 mojo::ApplicationRunnerChromium runner(new mojo::examples::WindowManager);
559 return runner.Run(application_request);
560 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698