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.
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/macros.h"
13 #include "base/message_loop/message_loop.h"
14 #include "base/path_service.h"
15 #include "mojo/examples/aura_demo/demo_screen.h"
16 #include "mojo/examples/aura_demo/window_tree_host_mojo.h"
17 #include "mojo/examples/launcher/launcher.mojom.h"
18 #include "mojo/public/bindings/allocation_scope.h"
19 #include "mojo/public/bindings/remote_ptr.h"
20 #include "mojo/public/gles2/gles2_cpp.h"
21 #include "mojo/public/shell/application.h"
22 #include "mojo/public/shell/shell.mojom.h"
23 #include "mojo/public/system/core.h"
24 #include "mojo/public/system/macros.h"
25 #include "mojo/services/native_viewport/native_viewport.mojom.h"
26 #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"
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_event_dispatcher.h"
35 #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"
55 #define LAUNCHER_EXPORT __declspec(dllexport)
58 #define LAUNCHER_EXPORT __attribute__((visibility("default")))
64 class MinimalInputEventFilter
: public ui::internal::InputMethodDelegate
,
65 public ui::EventHandler
{
67 explicit MinimalInputEventFilter(aura::Window
* 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
,
77 virtual ~MinimalInputEventFilter() {
78 root_
->RemovePreTargetHandler(this);
79 root_
->SetProperty(aura::client::kRootWindowInputMethodKey
,
80 static_cast<ui::InputMethod
*>(NULL
));
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();
93 if (input_method_
->DispatchKeyEvent(*event
))
94 event
->StopPropagation();
98 // ui::internal::InputMethodDelegate:
99 virtual bool DispatchKeyEventPostIME(const ui::KeyEvent
& event
) OVERRIDE
{
100 ui::TranslatedKeyEvent
aura_event(event
);
101 ui::EventDispatchDetails details
=
102 root_
->GetHost()->dispatcher()->OnEventFromSource(&aura_event
);
103 return aura_event
.handled() || details
.dispatcher_destroyed
;
107 scoped_ptr
<ui::InputMethod
> input_method_
;
109 DISALLOW_COPY_AND_ASSIGN(MinimalInputEventFilter
);
112 class LauncherWindowTreeClient
: public aura::client::WindowTreeClient
{
114 explicit LauncherWindowTreeClient(aura::Window
* window
) : window_(window
) {
115 aura::client::SetWindowTreeClient(window_
, this);
118 virtual ~LauncherWindowTreeClient() {
119 aura::client::SetWindowTreeClient(window_
, NULL
);
122 // Overridden from aura::client::WindowTreeClient:
123 virtual aura::Window
* GetDefaultParent(aura::Window
* context
,
124 aura::Window
* window
,
125 const gfx::Rect
& bounds
) OVERRIDE
{
130 aura::Window
* window_
;
132 DISALLOW_COPY_AND_ASSIGN(LauncherWindowTreeClient
);
135 // Called when the user has submitted a URL by pressing Enter.
138 virtual void OnURLEntered(const std::string
& url_text
) = 0;
141 virtual ~URLReceiver() {}
144 class LauncherController
: public views::TextfieldController
{
146 explicit LauncherController(URLReceiver
* url_receiver
)
147 : url_receiver_(url_receiver
) {}
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
);
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
);
165 views::Textfield
* textfield
= new views::Textfield
;
166 textfield
->set_controller(this);
167 container
->AddChildView(textfield
);
168 textfield
->RequestFocus();
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());
181 printf("Enter pressed with URL: %s\n", url
.spec().c_str());
182 url_receiver_
->OnURLEntered(url
.spec());
187 URLReceiver
* url_receiver_
;
189 DISALLOW_COPY_AND_ASSIGN(LauncherController
);
192 class LauncherImpl
: public Application
,
196 explicit LauncherImpl(MojoHandle shell_handle
)
197 : Application(shell_handle
),
198 launcher_controller_(this),
199 pending_show_(false) {
200 screen_
.reset(DemoScreen::Create());
201 gfx::Screen::SetScreenInstance(gfx::SCREEN_TYPE_NATIVE
, screen_
.get());
203 InterfacePipe
<NativeViewport
, AnyInterface
> pipe
;
205 AllocationScope scope
;
206 shell()->Connect("mojo:mojo_native_viewport_service",
207 pipe
.handle_to_peer
.Pass());
209 window_tree_host_
.reset(new WindowTreeHostMojo(
210 pipe
.handle_to_self
.Pass(), gfx::Rect(50, 50, 450, 60),
211 base::Bind(&LauncherImpl::HostContextCreated
, base::Unretained(this))));
215 // Overridden from Application:
216 virtual void AcceptConnection(const mojo::String
& url
,
217 ScopedMessagePipeHandle handle
) OVERRIDE
{
218 launcher_client_
.reset(
219 MakeScopedHandle(LauncherClientHandle(handle
.release().value())).Pass(),
223 // Overridden from Launcher:
224 virtual void Show() OVERRIDE
{
225 if (!window_tree_host_
.get()) {
226 pending_show_
= true;
229 window_tree_host_
->Show();
231 virtual void Hide() OVERRIDE
{
232 window_tree_host_
->Hide();
235 // Overridden from URLReceiver:
236 virtual void OnURLEntered(const std::string
& url_text
) OVERRIDE
{
237 AllocationScope scope
;
238 launcher_client_
->OnURLEntered(url_text
);
241 void HostContextCreated() {
242 window_tree_host_
->InitHost();
243 window_tree_host_
->window()->SetBounds(gfx::Rect(450, 60));
245 focus_client_
.reset(new aura::test::TestFocusClient());
246 aura::client::SetFocusClient(window_tree_host_
->window(),
247 focus_client_
.get());
248 activation_client_
.reset(
249 new aura::client::DefaultActivationClient(window_tree_host_
->window()));
250 capture_client_
.reset(
251 new aura::client::DefaultCaptureClient(window_tree_host_
->window()));
252 ime_filter_
.reset(new MinimalInputEventFilter(window_tree_host_
->window()));
254 window_tree_client_
.reset(
255 new LauncherWindowTreeClient(window_tree_host_
->window()));
257 launcher_controller_
.InitInWindow(window_tree_host_
->window());
260 pending_show_
= false;
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_
;
272 LauncherController launcher_controller_
;
274 RemotePtr
<LauncherClient
> launcher_client_
;
275 scoped_ptr
<aura::WindowTreeHost
> window_tree_host_
;
280 } // namespace examples
283 extern "C" LAUNCHER_EXPORT MojoResult CDECL
MojoMain(
284 MojoHandle shell_handle
) {
285 CommandLine::Init(0, NULL
);
286 base::AtExitManager at_exit
;
287 base::i18n::InitializeICU();
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
);
295 base::MessageLoop loop
;
296 mojo::GLES2Initializer gles2
;
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();
302 mojo::examples::LauncherImpl
launcher(shell_handle
);
305 return MOJO_RESULT_OK
;