blob: a641c0f73d9def059031eb54baf348ee7a8f9ce7 [file] [log] [blame]
[email protected]bddb2842014-01-27 22:38:191// 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"
[email protected]e9da2b72014-03-18 17:07:2512#include "base/macros.h"
[email protected]bddb2842014-01-27 22:38:1913#include "base/message_loop/message_loop.h"
14#include "base/path_service.h"
15#include "mojo/examples/aura_demo/demo_screen.h"
[email protected]e8cf7332014-02-14 18:54:5816#include "mojo/examples/aura_demo/window_tree_host_mojo.h"
[email protected]a4b0f4082014-02-27 22:07:4317#include "mojo/examples/launcher/launcher.mojom.h"
[email protected]811f5f2f12014-01-28 06:03:4318#include "mojo/public/bindings/allocation_scope.h"
19#include "mojo/public/bindings/remote_ptr.h"
[email protected]bddb2842014-01-27 22:38:1920#include "mojo/public/gles2/gles2_cpp.h"
[email protected]06863b392014-02-13 17:54:2921#include "mojo/public/shell/application.h"
[email protected]a4b0f4082014-02-27 22:07:4322#include "mojo/public/shell/shell.mojom.h"
[email protected]bddb2842014-01-27 22:38:1923#include "mojo/public/system/core.h"
24#include "mojo/public/system/macros.h"
[email protected]a4b0f4082014-02-27 22:07:4325#include "mojo/services/native_viewport/native_viewport.mojom.h"
[email protected]bddb2842014-01-27 22:38:1926#include "ui/aura/client/aura_constants.h"
27#include "ui/aura/client/default_activation_client.h"
28#include "ui/aura/client/default_capture_client.h"
29#include "ui/aura/client/window_tree_client.h"
30#include "ui/aura/env.h"
[email protected]bddb2842014-01-27 22:38:1931#include "ui/aura/test/test_focus_client.h"
32#include "ui/aura/window.h"
33#include "ui/aura/window_delegate.h"
[email protected]fcc51c952014-02-21 21:31:2634#include "ui/aura/window_event_dispatcher.h"
[email protected]bddb2842014-01-27 22:38:1935#include "ui/aura/window_tree_host.h"
36#include "ui/base/hit_test.h"
37#include "ui/base/ime/input_method.h"
38#include "ui/base/ime/input_method_delegate.h"
39#include "ui/base/ime/input_method_factory.h"
40#include "ui/base/resource/resource_bundle.h"
41#include "ui/gfx/canvas.h"
42#include "ui/views/background.h"
43#include "ui/views/border.h"
44#include "ui/views/controls/textfield/textfield.h"
45#include "ui/views/controls/textfield/textfield_controller.h"
46#include "ui/views/layout/fill_layout.h"
47#include "ui/views/view.h"
48#include "ui/views/widget/widget.h"
49#include "url/gurl.h"
50
51#if defined(WIN32)
52#if !defined(CDECL)
53#define CDECL __cdecl
54#endif
55#define LAUNCHER_EXPORT __declspec(dllexport)
56#else
57#define CDECL
58#define LAUNCHER_EXPORT __attribute__((visibility("default")))
59#endif
60
61namespace mojo {
62namespace examples {
63
64class MinimalInputEventFilter : public ui::internal::InputMethodDelegate,
65 public ui::EventHandler {
66 public:
67 explicit MinimalInputEventFilter(aura::Window* root)
68 : root_(root),
69 input_method_(ui::CreateInputMethod(this,
70 gfx::kNullAcceleratedWidget)) {
71 input_method_->Init(true);
72 root_->AddPreTargetHandler(this);
73 root_->SetProperty(aura::client::kRootWindowInputMethodKey,
74 input_method_.get());
75 }
76
77 virtual ~MinimalInputEventFilter() {
78 root_->RemovePreTargetHandler(this);
79 root_->SetProperty(aura::client::kRootWindowInputMethodKey,
80 static_cast<ui::InputMethod*>(NULL));
81 }
82
83 private:
84 // ui::EventHandler:
85 virtual void OnKeyEvent(ui::KeyEvent* event) OVERRIDE {
86 const ui::EventType type = event->type();
87 if (type == ui::ET_TRANSLATED_KEY_PRESS ||
88 type == ui::ET_TRANSLATED_KEY_RELEASE) {
89 // The |event| is already handled by this object, change the type of the
90 // event to ui::ET_KEY_* and pass it to the next filter.
91 static_cast<ui::TranslatedKeyEvent*>(event)->ConvertToKeyEvent();
92 } else {
93 if (input_method_->DispatchKeyEvent(*event))
94 event->StopPropagation();
95 }
96 }
97
[email protected]086e6d42014-01-30 13:38:5498 // ui::internal::InputMethodDelegate:
99 virtual bool DispatchKeyEventPostIME(const ui::KeyEvent& event) OVERRIDE {
100 ui::TranslatedKeyEvent aura_event(event);
[email protected]5da34bd2014-01-31 08:24:49101 ui::EventDispatchDetails details =
[email protected]2374d1812014-03-04 03:42:27102 root_->GetHost()->dispatcher()->OnEventFromSource(&aura_event);
[email protected]5da34bd2014-01-31 08:24:49103 return aura_event.handled() || details.dispatcher_destroyed;
[email protected]bddb2842014-01-27 22:38:19104 }
105
106 aura::Window* root_;
107 scoped_ptr<ui::InputMethod> input_method_;
108
109 DISALLOW_COPY_AND_ASSIGN(MinimalInputEventFilter);
110};
111
112class LauncherWindowTreeClient : public aura::client::WindowTreeClient {
113 public:
114 explicit LauncherWindowTreeClient(aura::Window* window) : window_(window) {
115 aura::client::SetWindowTreeClient(window_, this);
116 }
117
118 virtual ~LauncherWindowTreeClient() {
119 aura::client::SetWindowTreeClient(window_, NULL);
120 }
121
122 // Overridden from aura::client::WindowTreeClient:
123 virtual aura::Window* GetDefaultParent(aura::Window* context,
124 aura::Window* window,
125 const gfx::Rect& bounds) OVERRIDE {
126 return window_;
127 }
128
129 private:
130 aura::Window* window_;
131
132 DISALLOW_COPY_AND_ASSIGN(LauncherWindowTreeClient);
133};
134
[email protected]1fd496142014-01-29 05:16:02135// Called when the user has submitted a URL by pressing Enter.
136class URLReceiver {
137 public:
138 virtual void OnURLEntered(const std::string& url_text) = 0;
139
140 protected:
141 virtual ~URLReceiver() {}
142};
143
[email protected]bddb2842014-01-27 22:38:19144class LauncherController : public views::TextfieldController {
145 public:
[email protected]1fd496142014-01-29 05:16:02146 explicit LauncherController(URLReceiver* url_receiver)
147 : url_receiver_(url_receiver) {}
[email protected]bddb2842014-01-27 22:38:19148
149 void InitInWindow(aura::Window* parent) {
150 views::Widget* widget = new views::Widget;
151 views::Widget::InitParams params(views::Widget::InitParams::TYPE_POPUP);
152 params.parent = parent;
153 params.bounds = parent->bounds();
154 params.can_activate = true;
155 widget->Init(params);
156
157 views::View* container = new views::View;
158 container->set_background(
159 views::Background::CreateSolidBackground(SK_ColorYELLOW));
160 container->SetBorder(
161 views::Border::CreateEmptyBorder(10, 10, 10, 10));
162 container->SetLayoutManager(new views::FillLayout);
163 widget->SetContentsView(container);
164
165 views::Textfield* textfield = new views::Textfield;
166 textfield->set_controller(this);
167 container->AddChildView(textfield);
[email protected]1fd496142014-01-29 05:16:02168 textfield->RequestFocus();
[email protected]bddb2842014-01-27 22:38:19169
170 container->Layout();
171
172 widget->Show();
173 }
174
175 private:
176 // Overridden from views::TextfieldController:
177 virtual bool HandleKeyEvent(views::Textfield* sender,
178 const ui::KeyEvent& key_event) OVERRIDE {
179 if (key_event.key_code() == ui::VKEY_RETURN) {
180 GURL url(sender->text());
[email protected]1fd496142014-01-29 05:16:02181 printf("Enter pressed with URL: %s\n", url.spec().c_str());
182 url_receiver_->OnURLEntered(url.spec());
[email protected]bddb2842014-01-27 22:38:19183 }
184 return false;
185 }
186
[email protected]1fd496142014-01-29 05:16:02187 URLReceiver* url_receiver_;
188
[email protected]bddb2842014-01-27 22:38:19189 DISALLOW_COPY_AND_ASSIGN(LauncherController);
190};
191
[email protected]06863b392014-02-13 17:54:29192class LauncherImpl : public Application,
[email protected]1fd496142014-01-29 05:16:02193 public Launcher,
194 public URLReceiver {
[email protected]bddb2842014-01-27 22:38:19195 public:
[email protected]06863b392014-02-13 17:54:29196 explicit LauncherImpl(MojoHandle shell_handle)
197 : Application(shell_handle),
198 launcher_controller_(this),
[email protected]1fd496142014-01-29 05:16:02199 pending_show_(false) {
[email protected]bddb2842014-01-27 22:38:19200 screen_.reset(DemoScreen::Create());
201 gfx::Screen::SetScreenInstance(gfx::SCREEN_TYPE_NATIVE, screen_.get());
202
[email protected]76b8e582014-02-11 14:44:25203 InterfacePipe<NativeViewport, AnyInterface> pipe;
204
[email protected]84e4d4f2014-02-04 23:06:38205 AllocationScope scope;
[email protected]06863b392014-02-13 17:54:29206 shell()->Connect("mojo:mojo_native_viewport_service",
207 pipe.handle_to_peer.Pass());
[email protected]76b8e582014-02-11 14:44:25208
[email protected]e8cf7332014-02-14 18:54:58209 window_tree_host_.reset(new WindowTreeHostMojo(
[email protected]76b8e582014-02-11 14:44:25210 pipe.handle_to_self.Pass(), gfx::Rect(50, 50, 450, 60),
[email protected]1fd496142014-01-29 05:16:02211 base::Bind(&LauncherImpl::HostContextCreated, base::Unretained(this))));
[email protected]bddb2842014-01-27 22:38:19212 }
213
[email protected]1fd496142014-01-29 05:16:02214 private:
[email protected]06863b392014-02-13 17:54:29215 // Overridden from Application:
[email protected]128daf62014-02-12 16:26:11216 virtual void AcceptConnection(const mojo::String& url,
[email protected]e9da2b72014-03-18 17:07:25217 ScopedMessagePipeHandle handle) OVERRIDE {
[email protected]76b8e582014-02-11 14:44:25218 launcher_client_.reset(
219 MakeScopedHandle(LauncherClientHandle(handle.release().value())).Pass(),
220 this);
[email protected]bddb2842014-01-27 22:38:19221 }
222
[email protected]1fd496142014-01-29 05:16:02223 // Overridden from Launcher:
224 virtual void Show() OVERRIDE {
[email protected]2f2620332014-02-28 10:07:38225 if (!window_tree_host_.get()) {
[email protected]1fd496142014-01-29 05:16:02226 pending_show_ = true;
227 return;
228 }
[email protected]2f2620332014-02-28 10:07:38229 window_tree_host_->Show();
[email protected]1fd496142014-01-29 05:16:02230 }
231 virtual void Hide() OVERRIDE {
[email protected]2f2620332014-02-28 10:07:38232 window_tree_host_->Hide();
[email protected]1fd496142014-01-29 05:16:02233 }
234
235 // Overridden from URLReceiver:
[email protected]96a21522014-01-29 05:56:20236 virtual void OnURLEntered(const std::string& url_text) OVERRIDE {
[email protected]1fd496142014-01-29 05:16:02237 AllocationScope scope;
238 launcher_client_->OnURLEntered(url_text);
239 }
240
[email protected]bddb2842014-01-27 22:38:19241 void HostContextCreated() {
[email protected]2f2620332014-02-28 10:07:38242 window_tree_host_->InitHost();
243 window_tree_host_->window()->SetBounds(gfx::Rect(450, 60));
[email protected]bddb2842014-01-27 22:38:19244
245 focus_client_.reset(new aura::test::TestFocusClient());
[email protected]2f2620332014-02-28 10:07:38246 aura::client::SetFocusClient(window_tree_host_->window(),
247 focus_client_.get());
[email protected]bddb2842014-01-27 22:38:19248 activation_client_.reset(
[email protected]2f2620332014-02-28 10:07:38249 new aura::client::DefaultActivationClient(window_tree_host_->window()));
[email protected]bddb2842014-01-27 22:38:19250 capture_client_.reset(
[email protected]2f2620332014-02-28 10:07:38251 new aura::client::DefaultCaptureClient(window_tree_host_->window()));
252 ime_filter_.reset(new MinimalInputEventFilter(window_tree_host_->window()));
[email protected]bddb2842014-01-27 22:38:19253
254 window_tree_client_.reset(
[email protected]2f2620332014-02-28 10:07:38255 new LauncherWindowTreeClient(window_tree_host_->window()));
[email protected]bddb2842014-01-27 22:38:19256
[email protected]2f2620332014-02-28 10:07:38257 launcher_controller_.InitInWindow(window_tree_host_->window());
[email protected]bddb2842014-01-27 22:38:19258
[email protected]1fd496142014-01-29 05:16:02259 if (pending_show_) {
260 pending_show_ = false;
261 Show();
262 }
[email protected]bddb2842014-01-27 22:38:19263 }
264
265 scoped_ptr<DemoScreen> screen_;
266 scoped_ptr<LauncherWindowTreeClient> window_tree_client_;
267 scoped_ptr<aura::client::DefaultActivationClient> activation_client_;
268 scoped_ptr<aura::client::FocusClient> focus_client_;
269 scoped_ptr<aura::client::DefaultCaptureClient> capture_client_;
270 scoped_ptr<ui::EventHandler> ime_filter_;
271
272 LauncherController launcher_controller_;
273
[email protected]1fd496142014-01-29 05:16:02274 RemotePtr<LauncherClient> launcher_client_;
[email protected]2f2620332014-02-28 10:07:38275 scoped_ptr<aura::WindowTreeHost> window_tree_host_;
[email protected]1fd496142014-01-29 05:16:02276
277 bool pending_show_;
[email protected]bddb2842014-01-27 22:38:19278};
279
280} // namespace examples
281} // namespace mojo
282
283extern "C" LAUNCHER_EXPORT MojoResult CDECL MojoMain(
284 MojoHandle shell_handle) {
285 CommandLine::Init(0, NULL);
286 base::AtExitManager at_exit;
287 base::i18n::InitializeICU();
288
289 base::FilePath pak_dir;
290 PathService::Get(base::DIR_MODULE, &pak_dir);
291 base::FilePath pak_file;
292 pak_file = pak_dir.Append(FILE_PATH_LITERAL("ui_test.pak"));
293 ui::ResourceBundle::InitSharedInstanceWithPakPath(pak_file);
294
295 base::MessageLoop loop;
296 mojo::GLES2Initializer gles2;
297
298 // TODO(beng): This crashes in a DCHECK on X11 because this thread's
299 // MessageLoop is not of TYPE_UI. I think we need a way to build
300 // Aura that doesn't define platform-specific stuff.
301 aura::Env::CreateInstance();
[email protected]06863b392014-02-13 17:54:29302 mojo::examples::LauncherImpl launcher(shell_handle);
[email protected]bddb2842014-01-27 22:38:19303 loop.Run();
304
[email protected]bddb2842014-01-27 22:38:19305 return MOJO_RESULT_OK;
306}