Views Omnibox: tolerate minor click-to-select-all dragging.
[chromium-blink-merge.git] / mojo / examples / launcher / launcher.cc
blob651a2676f846d6e6096b7dffb4656404be4c897f
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.
5 #include <stdio.h>
6 #include <string>
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/root_window_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/system/core.h"
20 #include "mojo/public/system/macros.h"
21 #include "mojom/launcher.h"
22 #include "mojom/native_viewport.h"
23 #include "mojom/shell.h"
24 #include "ui/aura/client/aura_constants.h"
25 #include "ui/aura/client/default_activation_client.h"
26 #include "ui/aura/client/default_capture_client.h"
27 #include "ui/aura/client/window_tree_client.h"
28 #include "ui/aura/env.h"
29 #include "ui/aura/root_window.h"
30 #include "ui/aura/test/test_focus_client.h"
31 #include "ui/aura/window.h"
32 #include "ui/aura/window_delegate.h"
33 #include "ui/aura/window_tree_host.h"
34 #include "ui/base/hit_test.h"
35 #include "ui/base/ime/input_method.h"
36 #include "ui/base/ime/input_method_delegate.h"
37 #include "ui/base/ime/input_method_factory.h"
38 #include "ui/base/resource/resource_bundle.h"
39 #include "ui/gfx/canvas.h"
40 #include "ui/views/background.h"
41 #include "ui/views/border.h"
42 #include "ui/views/controls/textfield/textfield.h"
43 #include "ui/views/controls/textfield/textfield_controller.h"
44 #include "ui/views/layout/fill_layout.h"
45 #include "ui/views/view.h"
46 #include "ui/views/widget/widget.h"
47 #include "url/gurl.h"
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
59 namespace mojo {
60 namespace examples {
62 class 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)) {
69 input_method_->Init(true);
70 root_->AddPreTargetHandler(this);
71 root_->SetProperty(aura::client::kRootWindowInputMethodKey,
72 input_method_.get());
75 virtual ~MinimalInputEventFilter() {
76 root_->RemovePreTargetHandler(this);
77 root_->SetProperty(aura::client::kRootWindowInputMethodKey,
78 static_cast<ui::InputMethod*>(NULL));
81 private:
82 // ui::EventHandler:
83 virtual void OnKeyEvent(ui::KeyEvent* event) OVERRIDE {
84 const ui::EventType type = event->type();
85 if (type == ui::ET_TRANSLATED_KEY_PRESS ||
86 type == ui::ET_TRANSLATED_KEY_RELEASE) {
87 // The |event| is already handled by this object, change the type of the
88 // event to ui::ET_KEY_* and pass it to the next filter.
89 static_cast<ui::TranslatedKeyEvent*>(event)->ConvertToKeyEvent();
90 } else {
91 if (input_method_->DispatchKeyEvent(*event))
92 event->StopPropagation();
96 // ui::internal::InputMethodDelegate:
97 virtual bool DispatchKeyEventPostIME(const ui::KeyEvent& event) OVERRIDE {
98 ui::TranslatedKeyEvent aura_event(event);
99 ui::EventDispatchDetails details =
100 root_->GetDispatcher()->OnEventFromSource(&aura_event);
101 return aura_event.handled() || details.dispatcher_destroyed;
104 aura::Window* root_;
105 scoped_ptr<ui::InputMethod> input_method_;
107 DISALLOW_COPY_AND_ASSIGN(MinimalInputEventFilter);
110 class LauncherWindowTreeClient : public aura::client::WindowTreeClient {
111 public:
112 explicit LauncherWindowTreeClient(aura::Window* window) : window_(window) {
113 aura::client::SetWindowTreeClient(window_, this);
116 virtual ~LauncherWindowTreeClient() {
117 aura::client::SetWindowTreeClient(window_, NULL);
120 // Overridden from aura::client::WindowTreeClient:
121 virtual aura::Window* GetDefaultParent(aura::Window* context,
122 aura::Window* window,
123 const gfx::Rect& bounds) OVERRIDE {
124 return window_;
127 private:
128 aura::Window* window_;
130 DISALLOW_COPY_AND_ASSIGN(LauncherWindowTreeClient);
133 // Called when the user has submitted a URL by pressing Enter.
134 class URLReceiver {
135 public:
136 virtual void OnURLEntered(const std::string& url_text) = 0;
138 protected:
139 virtual ~URLReceiver() {}
142 class LauncherController : public views::TextfieldController {
143 public:
144 explicit LauncherController(URLReceiver* url_receiver)
145 : url_receiver_(url_receiver) {}
147 void InitInWindow(aura::Window* parent) {
148 views::Widget* widget = new views::Widget;
149 views::Widget::InitParams params(views::Widget::InitParams::TYPE_POPUP);
150 params.parent = parent;
151 params.bounds = parent->bounds();
152 params.can_activate = true;
153 widget->Init(params);
155 views::View* container = new views::View;
156 container->set_background(
157 views::Background::CreateSolidBackground(SK_ColorYELLOW));
158 container->SetBorder(
159 views::Border::CreateEmptyBorder(10, 10, 10, 10));
160 container->SetLayoutManager(new views::FillLayout);
161 widget->SetContentsView(container);
163 views::Textfield* textfield = new views::Textfield;
164 textfield->set_controller(this);
165 container->AddChildView(textfield);
166 textfield->RequestFocus();
168 container->Layout();
170 widget->Show();
173 private:
174 // Overridden from views::TextfieldController:
175 virtual bool HandleKeyEvent(views::Textfield* sender,
176 const ui::KeyEvent& key_event) OVERRIDE {
177 if (key_event.key_code() == ui::VKEY_RETURN) {
178 GURL url(sender->text());
179 printf("Enter pressed with URL: %s\n", url.spec().c_str());
180 url_receiver_->OnURLEntered(url.spec());
182 return false;
185 URLReceiver* url_receiver_;
187 DISALLOW_COPY_AND_ASSIGN(LauncherController);
190 class LauncherImpl : public ShellClient,
191 public Launcher,
192 public URLReceiver {
193 public:
194 explicit LauncherImpl(ScopedMessagePipeHandle shell_handle)
195 : launcher_controller_(this),
196 shell_(shell_handle.Pass(), this),
197 pending_show_(false) {
198 screen_.reset(DemoScreen::Create());
199 gfx::Screen::SetScreenInstance(gfx::SCREEN_TYPE_NATIVE, screen_.get());
201 ScopedMessagePipeHandle client_handle, native_viewport_handle;
202 CreateMessagePipe(&client_handle, &native_viewport_handle);
203 AllocationScope scope;
204 shell_->Connect("mojo:mojo_native_viewport_service", client_handle.Pass());
205 root_window_host_.reset(new WindowTreeHostMojo(
206 native_viewport_handle.Pass(), gfx::Rect(50, 50, 450, 60),
207 base::Bind(&LauncherImpl::HostContextCreated, base::Unretained(this))));
210 private:
211 // Overridden from ShellClient:
212 virtual void AcceptConnection(ScopedMessagePipeHandle handle) MOJO_OVERRIDE {
213 launcher_client_.reset(handle.Pass(), this);
216 // Overridden from Launcher:
217 virtual void Show() OVERRIDE {
218 if (!root_window_.get()) {
219 pending_show_ = true;
220 return;
222 root_window_->host()->Show();
224 virtual void Hide() OVERRIDE {
225 root_window_->host()->Hide();
228 // Overridden from URLReceiver:
229 virtual void OnURLEntered(const std::string& url_text) OVERRIDE {
230 AllocationScope scope;
231 launcher_client_->OnURLEntered(url_text);
234 void HostContextCreated() {
235 aura::RootWindow::CreateParams params(gfx::Rect(450, 60));
236 params.host = root_window_host_.get();
237 root_window_.reset(new aura::RootWindow(params));
238 root_window_host_->set_delegate(root_window_.get());
239 root_window_->Init();
240 root_window_->window()->SetBounds(gfx::Rect(450, 60));
242 focus_client_.reset(new aura::test::TestFocusClient());
243 aura::client::SetFocusClient(root_window_->window(), focus_client_.get());
244 activation_client_.reset(
245 new aura::client::DefaultActivationClient(root_window_->window()));
246 capture_client_.reset(
247 new aura::client::DefaultCaptureClient(root_window_->window()));
248 ime_filter_.reset(new MinimalInputEventFilter(root_window_->window()));
250 window_tree_client_.reset(
251 new LauncherWindowTreeClient(root_window_->window()));
253 launcher_controller_.InitInWindow(root_window_->window());
255 if (pending_show_) {
256 pending_show_ = false;
257 Show();
261 scoped_ptr<DemoScreen> screen_;
262 scoped_ptr<LauncherWindowTreeClient> window_tree_client_;
263 scoped_ptr<aura::client::DefaultActivationClient> activation_client_;
264 scoped_ptr<aura::client::FocusClient> focus_client_;
265 scoped_ptr<aura::client::DefaultCaptureClient> capture_client_;
266 scoped_ptr<ui::EventHandler> ime_filter_;
268 LauncherController launcher_controller_;
270 RemotePtr<Shell> shell_;
271 RemotePtr<LauncherClient> launcher_client_;
272 scoped_ptr<WindowTreeHostMojo> root_window_host_;
273 scoped_ptr<aura::RootWindow> root_window_;
275 bool pending_show_;
278 } // namespace examples
279 } // namespace mojo
281 extern "C" LAUNCHER_EXPORT MojoResult CDECL MojoMain(
282 MojoHandle shell_handle) {
283 CommandLine::Init(0, NULL);
284 base::AtExitManager at_exit;
285 base::i18n::InitializeICU();
287 base::FilePath pak_dir;
288 PathService::Get(base::DIR_MODULE, &pak_dir);
289 base::FilePath pak_file;
290 pak_file = pak_dir.Append(FILE_PATH_LITERAL("ui_test.pak"));
291 ui::ResourceBundle::InitSharedInstanceWithPakPath(pak_file);
293 base::MessageLoop loop;
294 mojo::GLES2Initializer gles2;
296 // TODO(beng): This crashes in a DCHECK on X11 because this thread's
297 // MessageLoop is not of TYPE_UI. I think we need a way to build
298 // Aura that doesn't define platform-specific stuff.
299 aura::Env::CreateInstance();
300 mojo::examples::LauncherImpl launcher(
301 mojo::MakeScopedHandle(mojo::MessagePipeHandle(shell_handle)).Pass());
302 loop.Run();
304 return MOJO_RESULT_OK;