blob: f71294b89f006a611dcac022cf0b7ddb41ee10ec [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"
[email protected]78ecb7c2014-05-06 22:34:2415#include "mojo/aura/screen_mojo.h"
16#include "mojo/aura/window_tree_host_mojo.h"
[email protected]a4b0f4082014-02-27 22:07:4317#include "mojo/examples/launcher/launcher.mojom.h"
[email protected]0c8b23992014-04-01 14:49:1718#include "mojo/public/cpp/bindings/allocation_scope.h"
[email protected]e7a94442014-03-31 03:53:3619#include "mojo/public/cpp/gles2/gles2.h"
[email protected]157552a2014-03-31 20:17:0820#include "mojo/public/cpp/shell/application.h"
[email protected]2fb8c532014-03-28 13:23:2321#include "mojo/public/cpp/system/core.h"
[email protected]157552a2014-03-31 20:17:0822#include "mojo/public/interfaces/shell/shell.mojom.h"
[email protected]a4b0f4082014-02-27 22:07:4323#include "mojo/services/native_viewport/native_viewport.mojom.h"
[email protected]bddb2842014-01-27 22:38:1924#include "ui/aura/client/aura_constants.h"
[email protected]bddb2842014-01-27 22:38:1925#include "ui/aura/client/default_capture_client.h"
26#include "ui/aura/client/window_tree_client.h"
27#include "ui/aura/env.h"
[email protected]bddb2842014-01-27 22:38:1928#include "ui/aura/test/test_focus_client.h"
29#include "ui/aura/window.h"
30#include "ui/aura/window_delegate.h"
[email protected]fcc51c952014-02-21 21:31:2631#include "ui/aura/window_event_dispatcher.h"
[email protected]bddb2842014-01-27 22:38:1932#include "ui/aura/window_tree_host.h"
33#include "ui/base/hit_test.h"
34#include "ui/base/ime/input_method.h"
35#include "ui/base/ime/input_method_delegate.h"
36#include "ui/base/ime/input_method_factory.h"
37#include "ui/base/resource/resource_bundle.h"
38#include "ui/gfx/canvas.h"
39#include "ui/views/background.h"
40#include "ui/views/border.h"
41#include "ui/views/controls/textfield/textfield.h"
42#include "ui/views/controls/textfield/textfield_controller.h"
43#include "ui/views/layout/fill_layout.h"
44#include "ui/views/view.h"
45#include "ui/views/widget/widget.h"
[email protected]f3b1efd2014-04-30 04:48:2046#include "ui/wm/core/default_activation_client.h"
[email protected]bddb2842014-01-27 22:38:1947#include "url/gurl.h"
48
49#if defined(WIN32)
50#if !defined(CDECL)
51#define CDECL __cdecl
52#endif
53#define LAUNCHER_EXPORT __declspec(dllexport)
54#else
55#define CDECL
56#define LAUNCHER_EXPORT __attribute__((visibility("default")))
57#endif
58
59namespace mojo {
60namespace examples {
61
62class MinimalInputEventFilter : public ui::internal::InputMethodDelegate,
63 public ui::EventHandler {
64 public:
65 explicit MinimalInputEventFilter(aura::Window* root)
66 : root_(root),
67 input_method_(ui::CreateInputMethod(this,
68 gfx::kNullAcceleratedWidget)) {
[email protected]7d3470b2014-05-05 20:28:3569 ui::InitializeInputMethod();
[email protected]bddb2842014-01-27 22:38:1970 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
[email protected]086e6d42014-01-30 13:38:5497 // ui::internal::InputMethodDelegate:
98 virtual bool DispatchKeyEventPostIME(const ui::KeyEvent& event) OVERRIDE {
99 ui::TranslatedKeyEvent aura_event(event);
[email protected]5da34bd2014-01-31 08:24:49100 ui::EventDispatchDetails details =
[email protected]2374d1812014-03-04 03:42:27101 root_->GetHost()->dispatcher()->OnEventFromSource(&aura_event);
[email protected]5da34bd2014-01-31 08:24:49102 return aura_event.handled() || details.dispatcher_destroyed;
[email protected]bddb2842014-01-27 22:38:19103 }
104
105 aura::Window* root_;
106 scoped_ptr<ui::InputMethod> input_method_;
107
108 DISALLOW_COPY_AND_ASSIGN(MinimalInputEventFilter);
109};
110
111class 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
[email protected]1fd496142014-01-29 05:16:02134// Called when the user has submitted a URL by pressing Enter.
135class URLReceiver {
136 public:
137 virtual void OnURLEntered(const std::string& url_text) = 0;
138
139 protected:
140 virtual ~URLReceiver() {}
141};
142
[email protected]bddb2842014-01-27 22:38:19143class LauncherController : public views::TextfieldController {
144 public:
[email protected]1fd496142014-01-29 05:16:02145 explicit LauncherController(URLReceiver* url_receiver)
146 : url_receiver_(url_receiver) {}
[email protected]bddb2842014-01-27 22:38:19147
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();
[email protected]4f254232014-05-19 22:59:07153 params.activatable = views::Widget::InitParams::ACTIVATABLE_YES;
[email protected]bddb2842014-01-27 22:38:19154 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);
[email protected]1fd496142014-01-29 05:16:02167 textfield->RequestFocus();
[email protected]bddb2842014-01-27 22:38:19168
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());
[email protected]1fd496142014-01-29 05:16:02180 printf("Enter pressed with URL: %s\n", url.spec().c_str());
181 url_receiver_->OnURLEntered(url.spec());
[email protected]bddb2842014-01-27 22:38:19182 }
183 return false;
184 }
185
[email protected]1fd496142014-01-29 05:16:02186 URLReceiver* url_receiver_;
187
[email protected]bddb2842014-01-27 22:38:19188 DISALLOW_COPY_AND_ASSIGN(LauncherController);
189};
190
[email protected]eaae49d2014-05-16 06:04:21191class LauncherImpl : public InterfaceImpl<Launcher>,
[email protected]1fd496142014-01-29 05:16:02192 public URLReceiver {
[email protected]bddb2842014-01-27 22:38:19193 public:
[email protected]eaae49d2014-05-16 06:04:21194 explicit LauncherImpl(Application* app)
195 : app_(app),
196 launcher_controller_(this),
[email protected]1fd496142014-01-29 05:16:02197 pending_show_(false) {
[email protected]78ecb7c2014-05-06 22:34:24198 screen_.reset(ScreenMojo::Create());
[email protected]bddb2842014-01-27 22:38:19199 gfx::Screen::SetScreenInstance(gfx::SCREEN_TYPE_NATIVE, screen_.get());
200
[email protected]5e1a8322014-05-09 22:35:51201 NativeViewportPtr viewport;
[email protected]eaae49d2014-05-16 06:04:21202 app_->ConnectTo("mojo:mojo_native_viewport_service", &viewport);
[email protected]76b8e582014-02-11 14:44:25203
[email protected]e8cf7332014-02-14 18:54:58204 window_tree_host_.reset(new WindowTreeHostMojo(
[email protected]5e1a8322014-05-09 22:35:51205 viewport.Pass(), gfx::Rect(50, 50, 450, 60),
[email protected]1fd496142014-01-29 05:16:02206 base::Bind(&LauncherImpl::HostContextCreated, base::Unretained(this))));
[email protected]bddb2842014-01-27 22:38:19207 }
208
[email protected]1fd496142014-01-29 05:16:02209 private:
[email protected]1fd496142014-01-29 05:16:02210 // Overridden from Launcher:
211 virtual void Show() OVERRIDE {
[email protected]2f2620332014-02-28 10:07:38212 if (!window_tree_host_.get()) {
[email protected]1fd496142014-01-29 05:16:02213 pending_show_ = true;
214 return;
215 }
[email protected]2f2620332014-02-28 10:07:38216 window_tree_host_->Show();
[email protected]1fd496142014-01-29 05:16:02217 }
218 virtual void Hide() OVERRIDE {
[email protected]2f2620332014-02-28 10:07:38219 window_tree_host_->Hide();
[email protected]1fd496142014-01-29 05:16:02220 }
221
222 // Overridden from URLReceiver:
[email protected]96a21522014-01-29 05:56:20223 virtual void OnURLEntered(const std::string& url_text) OVERRIDE {
[email protected]1fd496142014-01-29 05:16:02224 AllocationScope scope;
[email protected]cb31dc92014-05-12 23:47:55225 client()->OnURLEntered(url_text);
[email protected]1fd496142014-01-29 05:16:02226 }
227
[email protected]bddb2842014-01-27 22:38:19228 void HostContextCreated() {
[email protected]2f2620332014-02-28 10:07:38229 window_tree_host_->InitHost();
230 window_tree_host_->window()->SetBounds(gfx::Rect(450, 60));
[email protected]bddb2842014-01-27 22:38:19231
232 focus_client_.reset(new aura::test::TestFocusClient());
[email protected]2f2620332014-02-28 10:07:38233 aura::client::SetFocusClient(window_tree_host_->window(),
234 focus_client_.get());
[email protected]f3b1efd2014-04-30 04:48:20235 new wm::DefaultActivationClient(window_tree_host_->window());
[email protected]bddb2842014-01-27 22:38:19236 capture_client_.reset(
[email protected]2f2620332014-02-28 10:07:38237 new aura::client::DefaultCaptureClient(window_tree_host_->window()));
238 ime_filter_.reset(new MinimalInputEventFilter(window_tree_host_->window()));
[email protected]bddb2842014-01-27 22:38:19239
240 window_tree_client_.reset(
[email protected]2f2620332014-02-28 10:07:38241 new LauncherWindowTreeClient(window_tree_host_->window()));
[email protected]bddb2842014-01-27 22:38:19242
[email protected]2f2620332014-02-28 10:07:38243 launcher_controller_.InitInWindow(window_tree_host_->window());
[email protected]bddb2842014-01-27 22:38:19244
[email protected]1fd496142014-01-29 05:16:02245 if (pending_show_) {
246 pending_show_ = false;
247 Show();
248 }
[email protected]bddb2842014-01-27 22:38:19249 }
250
[email protected]eaae49d2014-05-16 06:04:21251 Application* app_;
[email protected]78ecb7c2014-05-06 22:34:24252 scoped_ptr<ScreenMojo> screen_;
[email protected]bddb2842014-01-27 22:38:19253 scoped_ptr<LauncherWindowTreeClient> window_tree_client_;
[email protected]bddb2842014-01-27 22:38:19254 scoped_ptr<aura::client::FocusClient> focus_client_;
255 scoped_ptr<aura::client::DefaultCaptureClient> capture_client_;
256 scoped_ptr<ui::EventHandler> ime_filter_;
257
258 LauncherController launcher_controller_;
259
[email protected]2f2620332014-02-28 10:07:38260 scoped_ptr<aura::WindowTreeHost> window_tree_host_;
[email protected]1fd496142014-01-29 05:16:02261
262 bool pending_show_;
[email protected]bddb2842014-01-27 22:38:19263};
264
265} // namespace examples
266} // namespace mojo
267
268extern "C" LAUNCHER_EXPORT MojoResult CDECL MojoMain(
269 MojoHandle shell_handle) {
270 CommandLine::Init(0, NULL);
271 base::AtExitManager at_exit;
272 base::i18n::InitializeICU();
273
274 base::FilePath pak_dir;
275 PathService::Get(base::DIR_MODULE, &pak_dir);
276 base::FilePath pak_file;
277 pak_file = pak_dir.Append(FILE_PATH_LITERAL("ui_test.pak"));
278 ui::ResourceBundle::InitSharedInstanceWithPakPath(pak_file);
279
280 base::MessageLoop loop;
281 mojo::GLES2Initializer gles2;
282
283 // TODO(beng): This crashes in a DCHECK on X11 because this thread's
284 // MessageLoop is not of TYPE_UI. I think we need a way to build
285 // Aura that doesn't define platform-specific stuff.
[email protected]5b883abb2014-05-05 06:44:10286 aura::Env::CreateInstance(true);
[email protected]bddb2842014-01-27 22:38:19287
[email protected]5e1a8322014-05-09 22:35:51288 mojo::Application app(shell_handle);
[email protected]eaae49d2014-05-16 06:04:21289 app.AddService<mojo::examples::LauncherImpl>(&app);
[email protected]5e1a8322014-05-09 22:35:51290
291 loop.Run();
[email protected]bddb2842014-01-27 22:38:19292 return MOJO_RESULT_OK;
293}