Upstream version 5.34.104.0
[platform/framework/web/crosswalk.git] / src / mojo / examples / launcher / launcher.cc
1 // Copyright 2013 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 <stdio.h>
6 #include <string>
7
8 #include "base/at_exit.h"
9 #include "base/command_line.h"
10 #include "base/files/file_path.h"
11 #include "base/i18n/icu_util.h"
12 #include "base/message_loop/message_loop.h"
13 #include "base/path_service.h"
14 #include "mojo/examples/aura_demo/demo_screen.h"
15 #include "mojo/examples/aura_demo/window_tree_host_mojo.h"
16 #include "mojo/public/bindings/allocation_scope.h"
17 #include "mojo/public/bindings/remote_ptr.h"
18 #include "mojo/public/gles2/gles2_cpp.h"
19 #include "mojo/public/shell/application.h"
20 #include "mojo/public/system/core.h"
21 #include "mojo/public/system/macros.h"
22 #include "mojom/launcher.h"
23 #include "mojom/native_viewport.h"
24 #include "mojom/shell.h"
25 #include "ui/aura/client/aura_constants.h"
26 #include "ui/aura/client/default_activation_client.h"
27 #include "ui/aura/client/default_capture_client.h"
28 #include "ui/aura/client/window_tree_client.h"
29 #include "ui/aura/env.h"
30 #include "ui/aura/root_window.h"
31 #include "ui/aura/test/test_focus_client.h"
32 #include "ui/aura/window.h"
33 #include "ui/aura/window_delegate.h"
34 #include "ui/aura/window_tree_host.h"
35 #include "ui/base/hit_test.h"
36 #include "ui/base/ime/input_method.h"
37 #include "ui/base/ime/input_method_delegate.h"
38 #include "ui/base/ime/input_method_factory.h"
39 #include "ui/base/resource/resource_bundle.h"
40 #include "ui/gfx/canvas.h"
41 #include "ui/views/background.h"
42 #include "ui/views/border.h"
43 #include "ui/views/controls/textfield/textfield.h"
44 #include "ui/views/controls/textfield/textfield_controller.h"
45 #include "ui/views/layout/fill_layout.h"
46 #include "ui/views/view.h"
47 #include "ui/views/widget/widget.h"
48 #include "url/gurl.h"
49
50 #if defined(WIN32)
51 #if !defined(CDECL)
52 #define CDECL __cdecl
53 #endif
54 #define LAUNCHER_EXPORT __declspec(dllexport)
55 #else
56 #define CDECL
57 #define LAUNCHER_EXPORT __attribute__((visibility("default")))
58 #endif
59
60 namespace mojo {
61 namespace examples {
62
63 class MinimalInputEventFilter : public ui::internal::InputMethodDelegate,
64                                 public ui::EventHandler {
65  public:
66   explicit MinimalInputEventFilter(aura::Window* root)
67       : root_(root),
68         input_method_(ui::CreateInputMethod(this,
69                                             gfx::kNullAcceleratedWidget)) {
70     input_method_->Init(true);
71     root_->AddPreTargetHandler(this);
72     root_->SetProperty(aura::client::kRootWindowInputMethodKey,
73                        input_method_.get());
74   }
75
76   virtual ~MinimalInputEventFilter() {
77     root_->RemovePreTargetHandler(this);
78     root_->SetProperty(aura::client::kRootWindowInputMethodKey,
79                        static_cast<ui::InputMethod*>(NULL));
80   }
81
82  private:
83   // ui::EventHandler:
84   virtual void OnKeyEvent(ui::KeyEvent* event) OVERRIDE {
85     const ui::EventType type = event->type();
86     if (type == ui::ET_TRANSLATED_KEY_PRESS ||
87         type == ui::ET_TRANSLATED_KEY_RELEASE) {
88       // The |event| is already handled by this object, change the type of the
89       // event to ui::ET_KEY_* and pass it to the next filter.
90       static_cast<ui::TranslatedKeyEvent*>(event)->ConvertToKeyEvent();
91     } else {
92       if (input_method_->DispatchKeyEvent(*event))
93         event->StopPropagation();
94     }
95   }
96
97   // ui::internal::InputMethodDelegate:
98   virtual bool DispatchKeyEventPostIME(const ui::KeyEvent& event) OVERRIDE {
99     ui::TranslatedKeyEvent aura_event(event);
100     ui::EventDispatchDetails details =
101         root_->GetDispatcher()->OnEventFromSource(&aura_event);
102     return aura_event.handled() || details.dispatcher_destroyed;
103   }
104
105   aura::Window* root_;
106   scoped_ptr<ui::InputMethod> input_method_;
107
108   DISALLOW_COPY_AND_ASSIGN(MinimalInputEventFilter);
109 };
110
111 class LauncherWindowTreeClient : public aura::client::WindowTreeClient {
112  public:
113   explicit LauncherWindowTreeClient(aura::Window* window) : window_(window) {
114     aura::client::SetWindowTreeClient(window_, this);
115   }
116
117   virtual ~LauncherWindowTreeClient() {
118     aura::client::SetWindowTreeClient(window_, NULL);
119   }
120
121   // Overridden from aura::client::WindowTreeClient:
122   virtual aura::Window* GetDefaultParent(aura::Window* context,
123                                          aura::Window* window,
124                                          const gfx::Rect& bounds) OVERRIDE {
125     return window_;
126   }
127
128  private:
129   aura::Window* window_;
130
131   DISALLOW_COPY_AND_ASSIGN(LauncherWindowTreeClient);
132 };
133
134 // Called when the user has submitted a URL by pressing Enter.
135 class URLReceiver {
136  public:
137   virtual void OnURLEntered(const std::string& url_text) = 0;
138
139  protected:
140   virtual ~URLReceiver() {}
141 };
142
143 class LauncherController : public views::TextfieldController {
144  public:
145   explicit LauncherController(URLReceiver* url_receiver)
146       : url_receiver_(url_receiver) {}
147
148   void InitInWindow(aura::Window* parent) {
149     views::Widget* widget = new views::Widget;
150     views::Widget::InitParams params(views::Widget::InitParams::TYPE_POPUP);
151     params.parent = parent;
152     params.bounds = parent->bounds();
153     params.can_activate = true;
154     widget->Init(params);
155
156     views::View* container = new views::View;
157     container->set_background(
158       views::Background::CreateSolidBackground(SK_ColorYELLOW));
159     container->SetBorder(
160       views::Border::CreateEmptyBorder(10, 10, 10, 10));
161     container->SetLayoutManager(new views::FillLayout);
162     widget->SetContentsView(container);
163
164     views::Textfield* textfield = new views::Textfield;
165     textfield->set_controller(this);
166     container->AddChildView(textfield);
167     textfield->RequestFocus();
168
169     container->Layout();
170
171     widget->Show();
172   }
173
174  private:
175   // Overridden from views::TextfieldController:
176   virtual bool HandleKeyEvent(views::Textfield* sender,
177                               const ui::KeyEvent& key_event) OVERRIDE {
178     if (key_event.key_code() == ui::VKEY_RETURN) {
179       GURL url(sender->text());
180       printf("Enter pressed with URL: %s\n", url.spec().c_str());
181       url_receiver_->OnURLEntered(url.spec());
182     }
183     return false;
184   }
185
186   URLReceiver* url_receiver_;
187
188   DISALLOW_COPY_AND_ASSIGN(LauncherController);
189 };
190
191 class LauncherImpl : public Application,
192                      public Launcher,
193                      public URLReceiver {
194  public:
195   explicit LauncherImpl(MojoHandle shell_handle)
196       : Application(shell_handle),
197         launcher_controller_(this),
198         pending_show_(false) {
199     screen_.reset(DemoScreen::Create());
200     gfx::Screen::SetScreenInstance(gfx::SCREEN_TYPE_NATIVE, screen_.get());
201
202     InterfacePipe<NativeViewport, AnyInterface> pipe;
203
204     AllocationScope scope;
205     shell()->Connect("mojo:mojo_native_viewport_service",
206                      pipe.handle_to_peer.Pass());
207
208     window_tree_host_.reset(new WindowTreeHostMojo(
209         pipe.handle_to_self.Pass(), gfx::Rect(50, 50, 450, 60),
210         base::Bind(&LauncherImpl::HostContextCreated, base::Unretained(this))));
211   }
212
213  private:
214   // Overridden from Application:
215   virtual void AcceptConnection(const mojo::String& url,
216                                 ScopedMessagePipeHandle handle) MOJO_OVERRIDE {
217     launcher_client_.reset(
218         MakeScopedHandle(LauncherClientHandle(handle.release().value())).Pass(),
219         this);
220   }
221
222   // Overridden from Launcher:
223   virtual void Show() OVERRIDE {
224     if (!root_window_.get()) {
225       pending_show_ = true;
226       return;
227     }
228     root_window_->host()->Show();
229   }
230   virtual void Hide() OVERRIDE {
231     root_window_->host()->Hide();
232   }
233
234   // Overridden from URLReceiver:
235   virtual void OnURLEntered(const std::string& url_text) OVERRIDE {
236     AllocationScope scope;
237     launcher_client_->OnURLEntered(url_text);
238   }
239
240   void HostContextCreated() {
241     aura::RootWindow::CreateParams params(gfx::Rect(450, 60));
242     params.host = window_tree_host_.get();
243     root_window_.reset(new aura::RootWindow(params));
244     window_tree_host_->set_delegate(root_window_.get());
245     root_window_->host()->InitHost();
246     root_window_->window()->SetBounds(gfx::Rect(450, 60));
247
248     focus_client_.reset(new aura::test::TestFocusClient());
249     aura::client::SetFocusClient(root_window_->window(), focus_client_.get());
250     activation_client_.reset(
251         new aura::client::DefaultActivationClient(root_window_->window()));
252     capture_client_.reset(
253         new aura::client::DefaultCaptureClient(root_window_->window()));
254     ime_filter_.reset(new MinimalInputEventFilter(root_window_->window()));
255
256     window_tree_client_.reset(
257         new LauncherWindowTreeClient(root_window_->window()));
258
259     launcher_controller_.InitInWindow(root_window_->window());
260
261     if (pending_show_) {
262       pending_show_ = false;
263       Show();
264     }
265   }
266
267   scoped_ptr<DemoScreen> screen_;
268   scoped_ptr<LauncherWindowTreeClient> window_tree_client_;
269   scoped_ptr<aura::client::DefaultActivationClient> activation_client_;
270   scoped_ptr<aura::client::FocusClient> focus_client_;
271   scoped_ptr<aura::client::DefaultCaptureClient> capture_client_;
272   scoped_ptr<ui::EventHandler> ime_filter_;
273
274   LauncherController launcher_controller_;
275
276   RemotePtr<LauncherClient> launcher_client_;
277   scoped_ptr<WindowTreeHostMojo> window_tree_host_;
278   scoped_ptr<aura::RootWindow> root_window_;
279
280   bool pending_show_;
281 };
282
283 }  // namespace examples
284 }  // namespace mojo
285
286 extern "C" LAUNCHER_EXPORT MojoResult CDECL MojoMain(
287     MojoHandle shell_handle) {
288   CommandLine::Init(0, NULL);
289   base::AtExitManager at_exit;
290   base::i18n::InitializeICU();
291
292   base::FilePath pak_dir;
293   PathService::Get(base::DIR_MODULE, &pak_dir);
294   base::FilePath pak_file;
295   pak_file = pak_dir.Append(FILE_PATH_LITERAL("ui_test.pak"));
296   ui::ResourceBundle::InitSharedInstanceWithPakPath(pak_file);
297
298   base::MessageLoop loop;
299   mojo::GLES2Initializer gles2;
300
301   // TODO(beng): This crashes in a DCHECK on X11 because this thread's
302   //             MessageLoop is not of TYPE_UI. I think we need a way to build
303   //             Aura that doesn't define platform-specific stuff.
304   aura::Env::CreateInstance();
305   mojo::examples::LauncherImpl launcher(shell_handle);
306   loop.Run();
307
308   return MOJO_RESULT_OK;
309 }