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 "mojo/application/application_runner_chromium.h"
6#include "mojo/examples/wm_flow/wm/frame_controller.h"
7#include "mojo/public/c/system/main.h"
8#include "mojo/public/cpp/application/application_delegate.h"
9#include "mojo/public/cpp/application/application_impl.h"
10#include "mojo/public/cpp/application/service_provider_impl.h"
11#include "mojo/services/public/cpp/view_manager/view_manager.h"
12#include "mojo/services/public/cpp/view_manager/view_manager_delegate.h"
13#include "mojo/services/public/cpp/view_manager/view_observer.h"
14#include "mojo/services/public/cpp/view_manager/window_manager_delegate.h"
15#include "mojo/services/public/interfaces/input_events/input_events.mojom.h"
16#include "mojo/services/window_manager/window_manager_app.h"
17#include "mojo/views/views_init.h"
18
19namespace examples {
20
21class SimpleWM : public mojo::ApplicationDelegate,
22                 public mojo::ViewManagerDelegate,
23                 public mojo::WindowManagerDelegate,
24                 public mojo::ViewObserver {
25 public:
26  SimpleWM()
27      : window_manager_app_(new mojo::WindowManagerApp(this, this)),
28        view_manager_(NULL),
29        root_(NULL),
30        window_container_(NULL),
31        next_window_origin_(10, 10) {}
32  virtual ~SimpleWM() {}
33
34 private:
35  // Overridden from mojo::ApplicationDelegate:
36  virtual void Initialize(mojo::ApplicationImpl* impl) MOJO_OVERRIDE {
37    window_manager_app_->Initialize(impl);
38  }
39  virtual bool ConfigureIncomingConnection(
40      mojo::ApplicationConnection* connection) MOJO_OVERRIDE {
41    window_manager_app_->ConfigureIncomingConnection(connection);
42    return true;
43  }
44
45  // Overridden from mojo::ViewManagerDelegate:
46  virtual void OnEmbed(
47      mojo::ViewManager* view_manager,
48      mojo::View* root,
49      mojo::ServiceProviderImpl* exported_services,
50      scoped_ptr<mojo::ServiceProvider> remote_service_provider) MOJO_OVERRIDE {
51    view_manager_ = view_manager;
52    root_ = root;
53
54    window_container_ = mojo::View::Create(view_manager_);
55    window_container_->SetBounds(root_->bounds());
56    root_->AddChild(window_container_);
57
58  }
59  virtual void OnViewManagerDisconnected(
60      mojo::ViewManager* view_manager) MOJO_OVERRIDE {
61    view_manager_ = NULL;
62    root_ = NULL;
63  }
64
65  // Overridden from mojo::WindowManagerDelegate:
66  virtual void Embed(
67      const mojo::String& url,
68      mojo::InterfaceRequest<mojo::ServiceProvider> service_provider)
69          MOJO_OVERRIDE {
70    mojo::View* app_view = NULL;
71    mojo::View* frame_view = CreateTopLevelWindow(&app_view);
72    window_container_->AddChild(frame_view);
73
74    // TODO(beng): We're dropping the |service_provider| passed from the client
75    //             on the floor here and passing our own. Seems like we should
76    //             be sending both. I'm not yet sure how this sould work for
77    //             N levels of proxying.
78    app_view->Embed(url, scoped_ptr<mojo::ServiceProviderImpl>(
79        new mojo::ServiceProviderImpl).Pass());
80  }
81  virtual void DispatchEvent(mojo::EventPtr event) MOJO_OVERRIDE {}
82
83  // Overridden from mojo::ViewObserver:
84  virtual void OnViewInputEvent(mojo::View* view,
85                                const mojo::EventPtr& event) MOJO_OVERRIDE {
86    if (event->action == mojo::EVENT_TYPE_MOUSE_RELEASED &&
87        event->flags & mojo::EVENT_FLAGS_RIGHT_MOUSE_BUTTON &&
88        view->parent() == window_container_) {
89      CloseWindow(view);
90    }
91  }
92  virtual void OnViewDestroyed(mojo::View* view) MOJO_OVERRIDE {
93    view->RemoveObserver(this);
94  }
95
96  void CloseWindow(mojo::View* view) {
97    mojo::View* first_child = view->children().front();
98    first_child->Destroy();
99    view->Destroy();
100    next_window_origin_.Offset(-50, -50);
101  }
102
103  mojo::View* CreateTopLevelWindow(mojo::View** app_view) {
104    mojo::View* frame_view = mojo::View::Create(view_manager_);
105    frame_view->SetBounds(gfx::Rect(next_window_origin_, gfx::Size(400, 400)));
106    next_window_origin_.Offset(50, 50);
107
108    new FrameController(frame_view, app_view);
109    return frame_view;
110  }
111
112  scoped_ptr<mojo::WindowManagerApp> window_manager_app_;
113
114  mojo::ViewManager* view_manager_;
115  mojo::View* root_;
116  mojo::View* window_container_;
117
118  gfx::Point next_window_origin_;
119
120  DISALLOW_COPY_AND_ASSIGN(SimpleWM);
121};
122
123}  // namespace examples
124
125MojoResult MojoMain(MojoHandle shell_handle) {
126  mojo::ViewsInit views_init;
127  mojo::ApplicationRunnerChromium runner(new examples::SimpleWM);
128  return runner.Run(shell_handle);
129}
130